繁体   English   中英

Java ClassLoader更改

[英]Java ClassLoader change

我有一些A类:

public class A {
    public A(String str) {
        System.out.println("Create A instance: " + str);
    }

    public void methodA() {
        System.out.println("#methodA1()");
    }
}

我的类加载器实现:

public class MyClassLoader extends ClassLoader {
    public MyClassLoader() {    
        super();
    }

    @Override
    public synchronized Class<?> loadClass(String name) 
            throws ClassNotFoundException {

        System.out.println("Load: " + name);

        return super.loadClass(name);
    }
}

现在我尝试更改当前线程中的默认类加载器:

import java.util.ArrayList;
import java.util.List;

public class ChangeLoaderTest {
    public static void main(String[] args) {
        // Save class loader so that we can restore later.
        ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();

        MyClassLoader newLoader = new MyClassLoader();
        try {
            // Set new classloader.
            Thread.currentThread().setContextClassLoader(newLoader);

            // My class.
            A a = new A("1");
            a.methodA();

            // Standard Java class.
            List<Integer> list = new ArrayList<Integer>();
            list.add(2);
            list.add(3);
        } finally {
            // Restore.
            Thread.currentThread().setContextClassLoader(oldLoader);
        }
    }
}

ChangeLoaderTest输出:

Create A instance: 1
#methodA1()

没有人

Load: ...

为什么? 我如何将ClassLoader更改为某个线程?

正如Marko Topolnik指出的那样, 上下文类加载器是供框架使用的 要自己使用类加载器,必须调用loadClass("somepackage.A") ,然后使用反射API创建A的新实例( Class.newInstance() )。

由于调用代码不知道A - 它使用不同的类加载器,因此您无法直接在源代码中使用A或其方法。 可以由普通类加载器加载的A的接口或基类可用于避免反射。

interface AIF{
        void someMethod();
 }
class A implements AIF{
      public void someMethod(){}
 }


public void test(){
     MyLoader loader = new MyLoader();
     Class cla = loader.loadClass("A");
     AIF a = (AIF) cla.newInstance();
     a.someMethod();

 }

contextClassLoader机制被像new这样的基本Java操作使用。 只有这样,各种框架才能访问负责的上下文类加载器并加载资源,类等.Java将始终使用加载正在执行的代码的类加载器。 它是您通过ChangeLoaderTest.class.getClassLoader()访问的那个 - 并且您无法对此进行任何操作。

我认为发生的事情是你的应用程序的类加载器也是你的类加载器的“父”可以找到A并加载它。 因此,您的类加载器将不会被搜索或用于加载A

说实话,我对类加载器的经验不多,但是如果你继承了一个使用URL作为类路径的子类(以便它可以找到类文件),那么父类加载器就无法加载它(不是类路径的一部分) ),将使用您的自定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM