Benutzerdefinierter Java-Klassenladeprogramm wird nicht zum Laden von Abhängigkeiten verwendet?
Ich habe versucht, ein benutzerdefiniertes Klassenladeprogramm einzurichten, das Klassen abfängt, um auszudrucken, welche Klassen in die Anwendung geladen werden. Der Klassenlader sieht so aus
public class MyClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("Loading: " + name);
return super.loadClass(name);
}
}
Es wird nur der Name aller geladenen Klassen ausgegeben. Wenn ich jedoch versuche, Code auszuführen,
import org.python.util.PythonInterpreter;
public class Scripts {
public String main(){
PythonInterpreter p = new PythonInterpreter();
p.exec("print 'Python ' + open('.gitignore').read()");
return "Success! Nothing broke";
}
}
über
MyClassLoader bcl = new MyClassLoader();
Class c = bcl.loadClass("Scripts");
Method m = c.getMethod("main");
String result = (String) m.invoke(c.getConstructor().newInstance());
es druckt aus
Loading: Scripts
Loading: java.lang.Object
Loading: java.lang.String
Loading: org.python.util.PythonInterpreter
Python build/
.idea/*
*.iml
RESULT: Success! Nothing broke
Welches scheint eher seltsam.org.python.util.PythonInterpreter
ist keine einfache Klasse, und es hängt von einer ganzen Reihe anderer Klassen in der aborg.python.util
Paket. Diese Klassen werden eindeutig geladen, für dieexec
würde Python-Code in der Lage, Sachen zu tun und meine Datei zu lesen. Aus irgendeinem Grund werden diese Klassen jedoch nicht von dem Klassenladeprogramm geladen, das sie geladen hatPythonInterpreter
.
Warum das? Ich hatte den Eindruck, dass der Klassenlader zum Laden einer Klasse verwendet wurdeC
würde verwendet, um alle anderen Klassen zu laden, die von benötigt werdenC
, aber das passiert hier eindeutig nicht. Ist diese Annahme falsch? Wenn ja, wie stelle ich es so ein, dass alle transitiven Abhängigkeiten vonC
werden von meinem Klassenlader geladen?
BEARBEITEN:
Einige Experimente mitURLClassLoader
, was vorgeschlagen wurde. Ich habe die Delegation in geändertloadClass()
:
try{
byte[] output = IOUtils.toByteArray(this.getResourceAsStream(name));
return instrument(defineClass(name, output, 0, output.length));
}catch(Exception e){
return instrument(super.loadClass(name));
}
Außerdem wurde MyClassLoader zu einer Unterklasse von URLClassLoader und nicht zu einem einfachen ClassLoader gemacht, wobei URLs über Folgendes abgerufen wurden:
super(((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs());
Aber es scheint nicht das Richtige zu sein. Im Speziellen,getResourceAsStream()
wirft mir für alle Klassen, die ich anfordere, Nullen zurück, auch für Nicht-Systemklassen wie diese Jython-Bibliothek.