Пользовательский загрузчик классов Java не используется для загрузки зависимостей?
Я пытался настроить собственный загрузчик классов, который перехватывает классы, чтобы распечатать, какие классы загружаются в приложение. Загрузчик классов выглядит так
public class MyClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("Loading: " + name);
return super.loadClass(name);
}
}
Он просто выдает имя всех классов, которые загружает. Тем не менее, когда я пытаюсь запустить какой-то код,
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";
}
}
через
MyClassLoader bcl = new MyClassLoader();
Class c = bcl.loadClass("Scripts");
Method m = c.getMethod("main");
String result = (String) m.invoke(c.getConstructor().newInstance());
это распечатывает
Loading: Scripts
Loading: java.lang.Object
Loading: java.lang.String
Loading: org.python.util.PythonInterpreter
Python build/
.idea/*
*.iml
RESULT: Success! Nothing broke
Что кажется довольно странным.org.python.util.PythonInterpreter
не простой класс, и это зависит от целого ряда других классов вorg.python.util
пакет. Эти классы явно загружаются, дляexec
'd python code умеет делать вещи и читать мой файл. Однако по какой-то причине эти классы не загружаются загрузчиком классов, который загрузилPythonInterpreter
.
Почему это? У меня сложилось впечатление, что загрузчик классов раньше загружал классC
будет использоваться для загрузки всех других классов, необходимыхC
, но этого явно не происходит. Это предположение ошибочно? Если это так, как я могу настроить его так, чтобы все переходные зависимостиC
загружаются моим загрузчиком классов?
РЕДАКТИРОВАТЬ:
Некоторые эксперименты с использованиемURLClassLoader
, который был предложен. Я изменил делегацию вloadClass()
:
try{
byte[] output = IOUtils.toByteArray(this.getResourceAsStream(name));
return instrument(defineClass(name, output, 0, output.length));
}catch(Exception e){
return instrument(super.loadClass(name));
}
а также сделал MyClassLoader подклассом URLClassLoader вместо простого ClassLoader, захватывая URL через:
super(((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs());
Но это не кажется правильным. В частности,getResourceAsStream()
возвращает мне нулевые значения для всех классов, которые я запрашиваю, даже для несистемных классов, таких как Jython lib.