【发布时间】:2012-10-30 04:52:14
【问题描述】:
我一直在尝试设置一个自定义类加载器,它拦截类以打印出哪些类正在加载到应用程序中。类加载器看起来像这样
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 的所有传递依赖项都由我的类加载器加载?
编辑:
建议使用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 库这样的非系统类,都向我抛出了空值。
【问题讨论】:
-
你为什么不直接调试它;)
-
这就是我一直在尝试做的!但是关于类加载过程的文档很少,实际操作是不透明和神秘的......
标签: java class jvm metaprogramming classloader