Niestandardowy program ładujący klasy Java nie jest używany do ładowania zależności?
Próbowałem skonfigurować niestandardowy program ładujący klasy, który przechwytuje klasy, aby wydrukować, które klasy są ładowane do aplikacji. Program ładujący wygląda tak
public class MyClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("Loading: " + name);
return super.loadClass(name);
}
}
Wyrzuca tylko nazwę wszystkich klas, które ładuje. Jednak gdy próbuję uruchomić jakiś kod,
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";
}
}
przez
MyClassLoader bcl = new MyClassLoader();
Class c = bcl.loadClass("Scripts");
Method m = c.getMethod("main");
String result = (String) m.invoke(c.getConstructor().newInstance());
to się drukuje
Loading: Scripts
Loading: java.lang.Object
Loading: java.lang.String
Loading: org.python.util.PythonInterpreter
Python build/
.idea/*
*.iml
RESULT: Success! Nothing broke
Co wydaje się dość dziwne.org.python.util.PythonInterpreter
nie jest klasą prostą i zależy od całej gamy innych klas worg.python.util
pakiet. Te klasy są wyraźnie ładowaneexec
Kod Pythona jest w stanie robić rzeczy i czytać mój plik. Z jakiegoś powodu klasy te nie są ładowane przez ładowany program ładującyPythonInterpreter
.
Dlaczego? Miałem wrażenie, że program ładujący klasę ładował klasęC
byłby użyty do załadowania wszystkich innych klas wymaganych przezC
, ale to się tutaj wyraźnie nie dzieje. Czy to założenie jest błędne? Jeśli tak, to jak ustawić go tak, aby wszystkie zależności przechodnieC
są ładowane przez mój program ładujący?
EDYTOWAĆ:
Niektóre eksperymenty z użyciemURLClassLoader
, co sugerowano. Zmodyfikowałem delegację wloadClass()
:
try{
byte[] output = IOUtils.toByteArray(this.getResourceAsStream(name));
return instrument(defineClass(name, output, 0, output.length));
}catch(Exception e){
return instrument(super.loadClass(name));
}
jak również stworzyłem podklasę MyClassLoader URLClassLoader zamiast zwykłego ClassLoader, pobierając adresy URL za pośrednictwem:
super(((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs());
Ale to nie wydaje się być właściwe. W szczególności,getResourceAsStream()
rzuca na mnie wartości null dla wszystkich żądanych klas, nawet klas niesystemowych, takich jak Jython lib.