みなさん、こんにちは。ご清聴ありがとうございました!私は簡単で明白な問題を抱えていますが、それでも行き詰まっています。
動的に作成されたJava=カスタムクラスローダーを介してサードパーティのライブラリで使用されるクラスを提供したい。
今私の問題は、自分で直接ロードしないときに、このクラスをロードするために使用するカスタムClassLoaderを設定するにはどうすればよいですか?
ClassLoaderを使用して特定のクラスをロードすると、それがこのクラスのClassLoaderになり、そのクラスからロードされたすべてのクラスが私のClassLoaderを介してチャネリングされると思いました。
この公式チュートリアルに従って、カスタムClassLoaderを作成しました: http://Java.Sun.com/developer/onlineTraining/Security/Fundamentals/magercises/ClassLoader/help.html 。
_public class DynamicClassloader extends ClassLoader {
private Map<String, Class<?>> classesMap = new HashMap<String, Class<?>>();
public DynamicClassloader(ClassLoader parent) {
// Also tried super(parent);
super(Sun.misc.Launcher.getLauncher().getClassLoader());
}
// Adding dynamically created classes
public void defineClass(String name, Class<?> clazz) {
classesMap.put(name, clazz);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// load from parent
Class<?> result = findLoadedClass(name);
if (result != null) {
return result;
}
try {
result = findSystemClass(name);
} catch (Exception e) {
// Ignore these
}
if (result != null) {
return result;
}
result = classesMap.get(name);
if (result == null) {
throw new ClassNotFoundException(name);
}
return result;
}
}
_
私はそれをそのようなコードのどこかで使用したかった:
_ClassLoader thisClassLoader = this.getClass().getClassLoader();
((DynamicClassloader) thisClassLoader).defineClass(className, dynClass);
_
私の問題は、サードパーティライブラリクラスのfindSystemClass(name)
を呼び出すと、親ClassLoaderがこのクラスを見つけ(クラスパス上にあるため)、そのClassLoaderになることです。また、親ClassLoaderはカスタムClassLoaderを認識していないため、事実上使用されなくなり、this.getClass().getClassLoader()
をDynamicClassLoaderにキャストできません。
別のアプローチは、JVM引数_-Djava.system.class.loader=my.DynamicClassloader
_を介して、ClassLoaderをシステムClassLoaderに設定することです。しかし、それは私にStackOverflowErrorを与えます:
_ ...
at de.unisaarland.cs.st.DynamicClassloader.findClass(DynamicClassloader.Java:39)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:307)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:248)
at Java.lang.ClassLoader.findSystemClass(ClassLoader.Java:916)
at de.unisaarland.cs.st.DynamicClassloader.findClass(DynamicClassloader.Java:39)
...
_
これは本当に簡単にできるはずですが、私は今アイデアから外れています...どんな助けでも大歓迎です!
私が質問を理解しているかわからない、あなたはサードパーティのlibを持っていて、クラスローダーを使ってクラスをロードしたいと思っています。
運が良ければ、サードパーティのlibはThread.currentThread().setContextClassLoader(myClassLoader)
を使用して設定できるスレッドコンテキストクラスローダーを使用します。同じスレッドで、このクラスローダーにThread.currentThread().getContextClassLoader()
...でアクセスできます。
別のポイントですが、コンテキストで重要であるかどうかはわかりませんが、親に委譲する前にクラスをロードしようとする、親から最後のクラスローダーを作成することもできます(最初に委任するのではなく)
コメントの後に編集:
ライブラリがスレッドコンテキストクラスローダーに依存していない場合、parent_lastクラスローダーは違いをもたらします。そのため、ライブラリをparent-lastクラスローダーでロードする必要があるため、クラスローダーをその親ローダー(親)ではなく、ライブラリのクラスローダーとして設定します。クラスローダーの)...
親優先の動作でクラスローダーを作成することもできますが、サードパーティのライブラリ用です...