JVM

…衆ロ難τιáo~ 提交于 2021-02-19 10:41:42

如果需要热部署,使用“双亲委派”是不行的,如何打破“双亲委派”呢~

一. 源代码

“双亲委派”源代码如下(ClassLoader.java):

public Class<?> loadClass(String name) throws ClassNotFoundException {
	return loadClass(name, false);
}

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

二. 模拟热加载

public class Hello {
    public Hello() {
    }

    public void test(){
        System.out.println(System.currentTimeMillis() + " => hello world");
    }
}

public class MyClassLoader extends ClassLoader{
    public static void main(String[] args) throws Exception {
        MyClassLoader m = new MyClassLoader();
        Class clazz = m.loadClass("com.test.Hello");
        clazz.getDeclaredMethod("test").invoke(clazz.getDeclaredConstructor().newInstance());


        while (true){
            TimeUnit.SECONDS.sleep(5);
            m = new MyClassLoader();
            clazz = m.loadClass("com.test.Hello");
            clazz.getDeclaredMethod("test").invoke(clazz.getDeclaredConstructor().newInstance());
        }
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        String path = "D:/project/java/test/javaTest/target/classes/" + name.replace('.', '/') + ".class";
        File f = new File(path);
        if(!f.exists()) {
            return super.loadClass(name);
        }

        try {
            InputStream is = new FileInputStream(f);
            byte[] b = new byte[is.available()];
            is.read(b);
            return defineClass(name, b, 0, b.length);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

运行结果:

1613700414784 => hello world

1613700419786 => hello world

1613700424787 => hello world


修改 Hello.java, 然后编译

public class Hello {
    public Hello() {
    }

    public void test(){
        System.out.println(System.currentTimeMillis() + " => hello world123");
    }
}

运行结果:

1613700414784 => hello world

1613700419786 => hello world

1613700424787 => hello world

1613700429788 => hello world

1613700434789 => hello world

1613700439789 => hello world

1613700444789 => hello world

1613700449790 => hello world123

1613700454790 => hello world123

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!