这是一个工作测试.每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如何重新加载webapps.它为每个webapp都有一个单独的ClassLoader,并在新的ClassLoader中加载一个新版本.旧的是GCed就像任何Java对象以及旧类一样.
请注意,我们使用TestClassLoader加载Test1,并通过反射调用其第一个方法.但是所有Test1依赖项将被隐式加载Test1类加载器,即所有Test1应用程序将被JVM加载到TestClassLoader中.