我试图在运行时切换的类加载器:

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();
    }
}

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变量在调试时进行测定)。

时,有可能使全部按新的线程使用给定的类加载器加载的类?

有帮助吗?

解决方案

在经由new Thread("test") { ... }创建匿名类具有包围实例的隐式引用。这个匿名类内类文字将使用封闭类的类加载器加载。

为了使这种测试工作,你应该拔出适当的可运行执行,并反射地使用所需的类加载器加载它;然后传递明确的线索。是这样的:

    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();

其他提示

我觉得InjectingClassLoader可能是重要的在这里。记住怎样类加载代表团的工作 - 如果您的层次结构不止一个类装载器可以找到类,最上面的类加载器将是一个负载。 (参见图21.2 这里)

由于InjectingClassLoader没有指定在其构造父,则默认为在抽象类加载器的构造,其将设置当前上下文类加载器作为InjectingClassLoader的父。因此,由于母公司(旧上下文的classloader)可以找到TestProxy,它总是加载InjectingClassLoader前级都有机会。

scroll top