Привет всем и спасибо за внимание! У меня есть проблема, которая должна быть легкой и очевидной, но я застрял.
Я хочу предоставить динамически созданные классы Java, которые будут использоваться сторонней библиотекой через пользовательский ClassLoader.
Теперь моя проблема заключается в следующем: как настроить собственный пользовательский класс 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, он эффективно выведен из использования и this.getClass().getClassLoader()
не может быть передан DynamicClassLoader.
Другим подходом было бы установить, что мой ClassLoader является системным ClassLoader через аргумент JVM -Djava.system.class.loader=my.DynamicClassloader
. Но это дает мне 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)
...
Это должно быть очень легко сделать, но я теперь не в идеях... любая помощь очень ценится!