首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更改类加载器

更改类加载器
EN

Stack Overflow用户
提问于 2010-05-12 19:14:32
回答 2查看 27.9K关注 0票数 12

我试图在运行时切换类加载程序:

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) throws Exception {
        final InjectingClassLoader classLoader = new InjectingClassLoader();
        Thread.currentThread().setContextClassLoader(classLoader);
        Thread thread = new Thread("test") {
            public void run() {
                System.out.println("running...");
                // approach 1
                ClassLoader cl = TestProxy.class.getClassLoader();
                try {
                    Class c = classLoader.loadClass("classloader.TestProxy");
                    Object o = c.newInstance();
                    c.getMethod("test", new Class[] {}).invoke(o);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // approach 2
                new TestProxy().test();
            };
        };
        thread.setContextClassLoader(classLoader);
        thread.start();
    }
}

以及:

代码语言:javascript
复制
public class TestProxy {
    public void test() {
        ClassLoader tcl = Thread.currentThread().getContextClassLoader();
        ClassLoader ccl = ClassToLoad.class.getClassLoader();
        ClassToLoad classToLoad = new ClassToLoad();
    }
}

(InjectingClassLoader是一个扩展org.apache.bcel.util.ClassLoader的类,它应该在询问它的父类之前加载修改过的类的版本)

我想使“方法1”和“方法2”的结果完全相同,但是看起来thread.setContextClassLoader( classloader )什么也不做,而且“方法2”总是使用系统类加载器(可以通过调试时比较tcl和ccl变量来确定)。

是否有可能使所有的类都由新线程使用给定的类加载器加载?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-14 06:49:35

您通过new Thread("test") { ... }创建的匿名类有一个对封闭实例的隐式引用。这个匿名类中的类文本将使用封闭类的ClassLoader加载。

为了使测试工作正常,您应该提取一个合适的可运行实现,并使用所需的ClassLoader反射加载它;然后显式地将它传递给线程。类似于:

代码语言:javascript
复制
    public final class MyRunnable implements Runnable {
        public void run() {
            System.out.println("running...");
            // etc...
        }
    }

    final Class runnableClass = classLoader.loadClass("classloader.MyRunnable");
    final Thread thread = new Thread((Runnable) runableClass.newInstance());

    thread.setContextClassLoader(classLoader); // this is unnecessary unless you you are using libraries that themselves call .getContextClassLoader()

    thread.start();
票数 17
EN

Stack Overflow用户

发布于 2010-05-12 19:39:59

我认为InjectingClassLoader在这里可能很重要。记住类加载委托是如何工作的--如果您的层次结构中有多个类加载器可以找到类,那么最顶层的类加载器就是加载类的类加载器。(见图21.2 这里)

由于InjectingClassLoader没有在其构造函数中指定父类,因此它将默认为抽象ClassLoader中的构造函数,这将将当前上下文类加载器设置为InjectingClassLoader的父类。因此,由于父类(旧的上下文类加载器)可以找到TestProxy,所以它总是在InjectingClassLoader有机会之前加载该类。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2822004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档