ここでは動作テストがあります。 5秒ごとにTest.main()はtest.Test1をリロードします。クラスをファイルシステムから呼び出して、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出力は、これは例えばTomcatがWebアプリケーションを再ロードする方法です
...
Hello !
Hello !
Hello !!!
Hello !!!
を変更し表示されます。 Webアプリケーションごとに個別のClassLoaderがあり、新しいClassLoaderに新しいバージョンがロードされます。古いものは、古いクラスと同様にJavaオブジェクトと同様にGCedされます。
TestClassLoaderでTest1をロードし、最初のメソッドをリフレクションで呼び出すことに注意してください。しかし、すべてのTest1依存関係には、Test1クラスローダーが暗黙的にロードされます。つまり、すべてのTest1アプリケーションがJVMによってTestClassLoaderにロードされます。
助けてくれてありがとう。ここで行ったように、新しいクラスローディングのたびに新しいクラスローダインスタンスがあることで、この問題が解決されました。 –