这是一个工作测试。每5秒钟Test.main()从文件系统重新加载test.Test1.class并调用Test1.hello()
package test;public class Test1 { public void hello() { System.out.println("Hello !"); }}public class Test { static class TestClassLoader extends ClassLoader { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (name.equals("test.Test1")) { try { InputStream is = Test.class.getClassLoader().getResourceAsStream("test/Test1.class"); byte[] buf = new byte[10000]; int len = is.read(buf); return defineClass(name, buf, 0, len); } catch (IOException e) { throw new ClassNotFoundException("", e); } } return getParent().loadClass(name); } } public static void main(String[] args) throws Exception { for (;;) { Class cls = new TestClassLoader().loadClass("test.Test1"); Object obj = cls.newInstance(); cls.getMethod("hello").invoke(obj); Thread.sleep(5000); } }}运行。然后更改并重新编译Test1
System.out.println("Hello !!!");在测试运行时。您将看到Test1.hello输出更改
...Hello !Hello !Hello !!!Hello !!!
例如,这就是Tomcat重新加载Web应用程序的方式。每个Web应用程序都有一个单独的ClassLoader,并在新的ClassLoader中加载新版本。就像任何Java对象以及旧类一样,旧的GC已被GC。
请注意,我们用TestClassLoader加载了Test1并通过反射调用了它的第一个方法。但是所有Test1依赖项都将通过Test1类加载器隐式加载,也就是说,所有Test1应用程序都将由JVM加载到TestClassLoader中。



