实现类的热部署

原创
2018/05/22 16:06
阅读数 88

即使是同个ClassLoader类的两个是实例,加载同个类也会不一样。所以实现类的热部署可以创建不同ClassLoader的实例对象,通过这两个不同的实例对象加载同名的类。发现xx.class文件被修改就执行加载。

package dou_dir_list;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class ClassReloader extends ClassLoader {
    private String classPath;
    String classname = "dou_dir_list.ListTest";
    public ClassReloader(String classPath){
        this.classPath = classPath;
    }
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = getData(name);
        if(classData == null){
            throw new ClassNotFoundException();
        }else{
            return defineClass(classname, classData, 0, classData.length);
        }
    }
    private byte[] getData(String className) {
        String path = classPath + className;
        try {
            InputStream is = new FileInputStream(path);
            ByteArrayOutputStream stream  = new ByteArrayOutputStream();
            byte[] buffer = new byte[2048];
            int num = 0;
            while((num = is.read(buffer)) != -1){
                stream.write(buffer,0,num);
            }
            return stream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static void main(String[] args) {
        /**
         * 同路径同名的某xx.class文件由两个不同的ClassLoader实例对象分别加载后再实例出的对象是两个不同的实例
         */
        try {
            String path = "E:/develop_workspaces/ssm/my_linked_list/bin/dou_dir_list/";
            
            ClassReloader reloader = new ClassReloader(path);
            Class r = reloader.findClass("ListTest.class");
            System.out.println(r.newInstance());
            
            ClassReloader reloader2 = new ClassReloader(path);
            Class r2 = reloader2.findClass("ListTest.class");
            System.out.println(r2.newInstance());
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
原理是这样,这种方式可以为在开发时修改类频繁重启节省些时间。但是原来已经被引用的对象就不好让JVM去栈中替换了,这违反JVM的设计原则。还有点问题是加载的类会进入PermGen,在Full GC时才回收,所以改动频繁时间长了可能会有溢出问题,所以也就开发时用用。JVM不知道运行时类型,只知道编译类型。可以像JSP一样不保存对象状态,创建使用后立即释放,再修改又是新的。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部