實現類的熱部署

即便是同個ClassLoader類的兩個是實例,加載同個類也會不同。因此實現類的熱部署能夠建立不一樣ClassLoader的實例對象,經過這兩個不一樣的實例對象加載同名的類。發現xx.class文件被修改就執行加載。java

package dou_dir_list;this

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

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同樣不保存對象狀態,建立使用後當即釋放,再修改又是新的。設計

相關文章
相關標籤/搜索