如何使用自定义ClassLoader?

大家好,感谢您的关注! 我有一个既容易又明显的问题,但我被卡住了。

我想提供动态创建的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不知道我的自定义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使用线程上下文类加载器,您可以使用Thread.currentThread().setContextClassLoader(myClassLoader) ,在同一个线程中,您可以使用Thread.currentThread().getContextClassLoader()访问此类加载器。 ..

另一点,但不确定它在您的上下文中是否重要,是您还可以编写一个父级最后一个类加载器,它将在委托给父级之前尝试加载该类(而不是先尝试委托)

在您的评论后编辑:

如果您的库不依赖于线程上下文类加载器,那么parent_last类加载器会有所不同,那么您必须使用父级最后一个类加载器加载库,从而将类加载器设置为库的类加载器而不是其父加载器(父类)你的类加载器)…

您也可以制作一个具有父亲优先行为的类加载器,但对于您的第三方库…

关于类加载器的良好链接……