próbuję przełączyć ładującego klasy w czasie wykonywania:Zmień classloader
public class Test {
public static void main(String[] args) throws Exception {
final InjectingClassLoader classLoader = new InjectingClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
Thread thread = new Thread("test") {
public void run() {
System.out.println("running...");
// approach 1
ClassLoader cl = TestProxy.class.getClassLoader();
try {
Class c = classLoader.loadClass("classloader.TestProxy");
Object o = c.newInstance();
c.getMethod("test", new Class[] {}).invoke(o);
} catch (Exception e) {
e.printStackTrace();
}
// approach 2
new TestProxy().test();
};
};
thread.setContextClassLoader(classLoader);
thread.start();
}
}
oraz:
public class TestProxy {
public void test() {
ClassLoader tcl = Thread.currentThread().getContextClassLoader();
ClassLoader ccl = ClassToLoad.class.getClassLoader();
ClassToLoad classToLoad = new ClassToLoad();
}
}
(InjectingClassLoader jest klasą rozszerzenie org.apache.bcel.util .ClassLoader, który powinien załadować zmodyfikowane wersje klas przed zapytaniem, czy jest dla nich rodzicem)
Chciałbym e, aby wynik "podejścia 1" i "podejścia 2" był dokładnie taki sam, ale wygląda na to, że thread.setContextClassLoader (classLoader) nic nie robi, a "podejście 2" zawsze używa systemowego programu ładującego klasy (można to ustalić porównując tcl i zmienne ccl podczas debugowania).
Czy to możliwe, aby wszystkie klas załadowane przez nowe zastosowanie gwintu danego classloader?
Nit: "refleksyjnie". Biorąc pod uwagę, że w pytaniu dotyczącym modułu ładującego klasy kontekst jest zamieszanie, można wspomnieć, że setContextClassLoader nie ma żadnego efektu, chyba że wątek wykonuje pewną operację, która wymaga jej ustawienia (np. Tworzenie SAXParser, wykonywanie wyszukiwania JNDI itd.). –
Naprawiono; refleksyjnie -> refleksyjnie. Dzięki. –