クラスをインターセプトして、どのクラスがアプリケーションにロードされているかを出力するカスタム クラスローダーをセットアップしようとしています。クラスローダーはこんな感じ
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));
}
また、プレーンな ClassLoader ではなく、MyClassLoader サブクラス URLClassLoader を作成し、次の方法で URL を取得します。
super(((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs());
しかし、それは正しいことではないようです。特に、getResourceAsStream()
Jython lib のような非システム クラスであっても、要求しているすべてのクラスに対して null が返されます。