java - 如何使用自定义 ClassLoader?

标签 java classloader

大家好,感谢关注!我有一个既简单又明显的问题,但我被困住了。

我想通过自定义 ClassLoader 交付动态创建的 Java 类,供第三方库使用。

现在我的问题是:当我自己不直接加载这些类时,如何设置我的自定义 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);

现在我的问题是,当我调用 3rd 方库类的 findSystemClass(name) 时,父 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)
    ...

这一定很容易做到,但我现在没有想法......非常感谢任何帮助!

最佳答案

不确定我是否理解这个问题,您有一个 3rd 方库,并且您希望它使用您的类加载器来加载类。

如果你很幸运,第三方库使用了你可以使用 Thread.currentThread().setContextClassLoader(myClassLoader) 设置的线程上下文类加载器,在同一个线程中你可以访问这个类加载器Thread.currentThread().getContextClassLoader()...

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

在您发表评论后编辑:

parent_last 类加载器如果你的库不依赖于线程上下文类加载器,那么你必须用你的 parent-last 类加载器加载库,从而将你的类加载器设置为库的类加载器而不是它的父加载器(您的类加载器的父级)...

您也可以创建一个具有父优先行为的类加载器,但对于您的 3rd 方库...

And a good link about classloaders...

关于java - 如何使用自定义 ClassLoader?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4095976/

相关文章:

java - 类型转换异常

在 Websphere 上运行 POI 3.8 时出现 java.lang.InknownClassChangeError

java - 如何初始化使用自定义类加载器动态加载的类?

java - 在编译时使用自定义类加载器

java - ClassLoader.loadClass() 令人惊讶地抛出 NoClassDefFoundError 而不是 ClassNotFoundException

Glassfish:如何让服务器对多个应用程序使用单个类加载器

java - jDTO Binder 上的 DTO 绑定(bind)生命周期

java - 如何找到一部分网格的坐标?

java - 在 Windows 7 上安装和导入 javafx

java - 同一个 BufferedImage 对象加载多个图像时出现内存泄漏