我一直在尝试设置一个自定义类加载器来拦截类以打印出哪些类正在加载到应用程序中。类加载器看起来像这样
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 代码能够做一些事情并读取我的文件。但是,由于某种原因,这些类没有被加载的类加载器加载PythonInterpreter
。
这是为什么?我的印象是用于加载类的类加载器C
将用于加载 所需的所有其他类C
,但这显然不会发生在这里。这个假设是错误的吗?如果是,我如何设置它以使C
我的类加载器加载的所有传递依赖项?
编辑:
建议使用 using 进行一些实验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 这样的非系统类,都向我抛出空值。