美文网首页
如何实现热加载

如何实现热加载

作者: zychen143 | 来源:发表于2017-09-15 12:26 被阅读0次

    运行一个程序HelloMain,他会循环调用另外一个类Worker.doit()方法。此时,对Worker.doit()方法做更新。要求 更新后,HelloMain可以发现新的版本。 可以选择替换class文件 ,也可以选择替换jar包。

    答:我在这里选择的是替换class. 这题的关键是发现class文件改变,用新的classloader去加载class文件,然后程序调用的也是通过新加载的class去调用。 由于Java有双亲委派模式加哉,故需要热部署的class必须通过自定义的classloader去加载。 强调同一个类的概念:1.类加载器负责加载所有的类,系统为所有被载入内存中的类生成一个java.lang.Class实例.一旦一个类被载入JVM中,同一个类就不会被再次载入了。2.在Java中,一个类用其全限定类名,包名和类名,作为标识;但在JVM中一个类用其全限定类名和其类加载器作为其唯一标识。 即,如果Worker被appclassloader加载过后,又被自定义classloader加载,它们两个不是同一个class.所以在我的程序中,Worker不能被appclassloader,即在我的程序中不能明确使用“Worker.doit()”。这里我是通过反射调用的,

    package leetcode.classLoad;
    
    import java.io.File;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.net.URLClassLoader;
    
    /**
     * @Author: 章源辰
     * @Date: 2017/9/15
     * @Description:
     */
    public class HelloMain {
        private URLClassLoader classLoader;
        private long lastTime;
        private Object worker;
        private String classDir="D:\\mywork\\aaa\\target\\classes\\";
    
        public static void main(String[] args) throws Exception{
            HelloMain helloMain = new HelloMain();
            helloMain.execute();
        }
    
        private void execute() throws Exception{
            while (true){
                if (checkIsNeedReload()){
                    System.out.println("检测到新版本,准备重新加载");
                    reload();
                    System.out.println("重新加载完成");
                }
                invokeMethod();
                Thread.sleep(1000);
            }
        }
    
        private void invokeMethod() throws Exception{
            Method method = worker.getClass().getDeclaredMethod("doit", null);
            method.invoke(worker, null);
        }
    
        private void reload() throws  Exception{
            classLoader = new MyClassLoader(new URL[]{
                    new URL("file:"+classDir)
            });
            worker = classLoader.loadClass("leetcode.classLoad.Worker").newInstance();
        }
    
        private boolean checkIsNeedReload() {
            File file = new File(classDir+"leetcode\\classLoad\\Worker.class");
            long newTime = file.lastModified();
            if (newTime > lastTime){
                lastTime = newTime;
                return true;
            }else {
                return false;
            }
        }
    }
    
    
    package leetcode.classLoad;
    
    /**
     * @Author: 章源辰
     * @Date: 2017/9/15
     * @Description:
     */
    public class Worker {
    
        public void doit(){
            System.out.println("调用work中的doit方法aaaaaa=======");
        }
    }
    
    
    package leetcode.classLoad;
    
    import java.net.URL;
    import java.net.URLClassLoader;
    
    /**
     * @Author: 章源辰
     * @Date: 2017/9/15
     * @Description:
     */
    public class MyClassLoader extends URLClassLoader {
    
        public MyClassLoader(URL[] urls) {
            super(urls);
        }
    
        @Override
        protected synchronized Class<?> loadClass(String name, boolean resolve)
                throws ClassNotFoundException {
            Class c = findLoadedClass(name);
            if (c == null) {
                try {
                    c = findClass(name);
                } catch (Exception e) {
                }
            }
            if (c == null) {
                c = super.loadClass(name, resolve);
            }
            return c;
        }
    
    }
    
    
    image.png

    相关文章

      网友评论

          本文标题:如何实现热加载

          本文链接:https://www.haomeiwen.com/subject/ryyssxtx.html