Java实现热替换

package test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;

public class DynamicLoader extends ClassLoader {

    private String baseDir;

    public DynamicLoader(String baseDir) {
        super();
        this.baseDir = baseDir;
    }

    private String getClassFile(String className){
        return baseDir+className.replace(".", "/")+".class";
    }

    protected Class findClass(String className) throws ClassNotFoundException {
        Class clazz = this.findLoadedClass(className);
        if (null == clazz) {
            try {
                String classFile = getClassFile(className);
                FileInputStream fis = new FileInputStream(classFile);
                FileChannel fileC = fis.getChannel();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                WritableByteChannel outC = Channels.newChannel(baos);
                ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
                int count = 0;
                while ((count = fileC.read(buffer)) > 0) {
                    buffer.flip();
                    outC.write(buffer);
                    buffer.clear();
                }
                fis.close();
                byte[] bytes = baos.toByteArray();
                clazz = defineClass(className, bytes, 0, bytes.length);
            } catch (Exception e) {
                System.out.println("can not load class "+className +" from DynamicLoader.");
            }
        }
        return clazz;
    }

    protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // First, check if the class has already been loaded
        Class re=findClass(name);
        if(re==null){
            return super.loadClass(name,resolve);
        }
        return re;
    }

}
package test;

public class Worker {

    public void doit(){
        System.out.println("I am version 3");
    }
}
package test;

import java.lang.reflect.Method;

public class HelloMain {

    public static void main(String[] args) throws Exception {

        while(true)
        {
            DynamicLoader loader =    new DynamicLoader("F:\\workspace\\HibernateSrc\\bin\\");
            Class clazz = loader.loadClass("test.Worker");
            Object instance = clazz.newInstance();
            Method doit = clazz.getDeclaredMethod("doit",null);
            doit.invoke(instance, null);
            Thread.sleep(2000);
        }

    }

}

思路:

在HelloMain里面定时的创建新的自定义ClassLoader,然后指定加载某个目录的class文件.加载的时候不是父类优先,而是子类优先模式.

自定义的ClassLoader找到Worker类后,反射穿件实例.

这里不能用new关键字在HelloMain类里面创建Worker实例,也能让反射生成的实例转型成Worker类型,因为那样会导致AppliationClassLoader加载Worker类.

如果被AppliationClassLoader加载了Worker类,那么新版本的Worker就不能再被Application ClassLoader加载了,一个ClassLoader里面同名的class只能有一个.

如果这个时候让AppliationClassLoader加载了老的Worker类,在替换的时候让自定义ClassLoader加载新版本的Woker类,则会出现ClassCastException.

因为这些Worker类来之不同的ClassLoader,比如下面代码会报ClassCastException.

DynamicLoader loader = new DynamicLoader("F:workspaceHibernateSrcbin");

Class clazz = loader.loadClass("test.Worker");

Worker instance = (Worker)clazz.newInstance();//ClassCastException error
instance.doit();

所以Worker类只能是让自定义的ClassLoader加载.同时下次要运行的时候,也要在创建一个新的自定义ClassLoader来加载.

参考 http://www.cnblogs.com/princessd8251/articles/3967569.html

时间: 2024-11-09 04:01:30

Java实现热替换的相关文章

基于Instrumentation的JAVA代码热替换

理类用来获取 Instrumentation 实例 package com.codeconch.util; import java.lang.instrument.Instrumentation; public class Monitor { private static Instrumentation instrumentation; public static void premain(String args, Instrumentation inst) { instrumentation

Java 类的热替换---转载

构建基于 Java 的在线升级系统 Java ClassLoader 技术剖析 在本文中,我们将不对 Java ClassLoader 的细节进行过于详细的讲解,而是关注于和构建在线升级系统相关的基础概念.关于 ClassLoader 的详细细节许多资料可以参考,有兴趣的读者可以自行研读. 要构建在线升级系统,一个重要的技术就是能够实现 Java 类的热替换 —— 也就是在不停止正在运行的系统的情况下进行类(对象)的升级替换.而 Java 的 ClassLoader 正是实现这项技术的基础. 在

(转)Java 类的热替换 —— 概念、设计与实现

构建基于 Java 的在线升级系统 对于许多关键性业务或者庞大的 Java 系统来说,如果必须暂停系统服务才能进行系统升级,既会大大影响到系统的可用性,同时也增加了系统的管理和维护成本.因此,如果能够方便地在不停止系统业务的情况下进行系统升级,则可以很好地解决上述问题.在本文中,我们将基于实例,对构建在线升级 Java 系统的基础技术和设计原则进行了深入的讲解.相信读者能够根据文中的技术构建出自己的在线升级系统来. Java ClassLoader 技术剖析 在本文中,我们将不对 Java Cl

Java 类的热替换 —— 概念、设计与实现

别人的一篇技术博客,直接摘抄过来,免得再查看找不到了(本人在看的过程中可能会对原文格式或文字有修改) 原文地址:http://blog.163.com/web_promise/blog/static/109631655201222804931240/ 在本文中,我们将不对 Java ClassLoader 的细节进行过于详细的讲解,而是关注于与构建在线升级系统相关的基础概念.关于 ClassLoader 的详细细节有许多资料可以参考,有兴趣的读者可以自行研读. 要构建在线升级系统,一个重要的技术

Java_类的热替换

转自:http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/#ibm-pcon Java ClassLoader 技术剖析 在本文中,我们将不对 Java ClassLoader 的细节进行过于详细的讲解,而是关注于和构建在线升级系统相关的基础概念.关于 ClassLoader 的详细细节许多资料可以参考,有兴趣的读者可以自行研读. 要构建在线升级系统,一个重要的技术就是能够实现 Java 类的热替换 —— 也就是在不停止正在运行的系

class卸载、热替换和Tomcat的热部署的分析

一 class的热替换 ClassLoader中重要的方法 loadClassClassLoader.loadClass(...) 是ClassLoader的入口点.当一个类没有指明用什么加载器加载的时候,JVM默认采用AppClassLoader加载器加载没有加载过的class,调用的方法的入口就是loadClass(…).如果一个class被自定义的ClassLoader加载,那么JVM也会调用这个自定义的ClassLoader.loadClass(…)方法来加载class内部引用的一些别的

Class热替换与卸载

概述 名词解释:所谓热部署,就是在应用正在运行的时候升级软件,却不需要重新启动应用.本文主要是分析Tomcat中关于热部署和JSP更新替换的原理,在此之前先介绍class的热替换和class的卸载的原理. Class热替换 ClassLoader中重要方法: loadClass:ClassLoader.loadClass(…) 是ClassLoader的入口点.当一个类没有指明用什么加载器加载的时候,JVM默认采用AppClassLoader加载器加载没有加载过的class,调用的方法的入口就是

【转】class卸载、热替换和Tomcat的热部署的分析

这篇文章主要是分析Tomcat中关于热部署和JSP更新替换的原理,在此之前先介绍class的热替换和class的卸载的原理. 一 class的热替换ClassLoader中重要的方法 loadClass ClassLoader.loadClass(...) 是ClassLoader的入口点.当一个类没有指明用什么加载器加载的时候,JVM默认采用AppClassLoader加载器加载没有加载过的class,调用的方法的入口就是loadClass(...).如果一个class被自定义的ClassLo

使用Browsersync热更新热替换,解放F5

超简单的入门小例子,有图有真相.当然也够我们在项目中使用.先看一下目录结构. 这里就使用了一个html和一个css样式表.接下来如下. 1. 安装 Node.js 不会安装node.js?太落伍了,懒得教你,自行百度吧. 2. 安装 BrowserSync 安装完node.js之后,在命令行输入 npm install -g browser-sync安装成功后. 2. 启动 BrowserSync 运行以下其中一条命令.Browsersync将创建一个本地服务器并自动打开你的浏览器后访问http