Sto cercando di cambiare il caricatore di classe in fase di esecuzione:Change 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();
}
}
e:
public class TestProxy {
public void test() {
ClassLoader tcl = Thread.currentThread().getContextClassLoader();
ClassLoader ccl = ClassToLoad.class.getClassLoader();
ClassToLoad classToLoad = new ClassToLoad();
}
}
(InjectingClassLoader è una classe che estende la org.apache.bcel.util .ClassLoader che dovrebbe caricare le versioni modificate delle classi prima di chiedere il genitore per loro)
I'd lik per rendere il risultato di "approccio 1" e "approccio 2" esattamente identico, ma sembra thread.setContextClassLoader (classLoader) non fa nulla e "approccio 2" utilizza sempre il classloader di sistema (può essere determinato confrontando tcl e le variabili ccl durante il debugging).
E 'possibile effettuare tutte le classi caricate dal nuovo thread utilizzare il classloader specificato?
Nit: "reflectively". Dato che c'è confusione nella domanda riguardante il caricatore di classi di contesto, si potrebbe menzionare che setContextClassLoader non ha alcun effetto a meno che il thread non esegua alcune operazioni che richiedono di essere impostato (ad esempio, creando un SAXParser, eseguendo una ricerca JNDI, ecc.). –
riparato; riflessivamente -> riflessivamente. Grazie. –