使用自定义类加载器加载静态方法

时间:2015-10-15 07:58:24

标签: java classloader static-methods

我有一个自定义类加载器,如下所示

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class MyClassLoader extends ClassLoader
{
    public String invoke(final String className, final String methodName, final String someString)
    {
        try {
            final ClassLoader classLoader = getClass().getClassLoader();
            final Class loadedClass = classLoader.loadClass(className);
            final Constructor constructor = loadedClass.getConstructor();
            final Object myClassObject = constructor.newInstance();
            final Method method = loadedClass.getMethod(methodName, String.class);
            final Object testStr = method.invoke(myClassObject, someString);
            System.out.println(loadedClass.getClassLoader());
            return (String) testStr;
        }
        catch (final ClassNotFoundException e) {
            e.printStackTrace();
        }
        catch (final Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

和一个名为Bus

的类
public class Bus
{
    public static String connection(final String incoming)
    {
        return "Bus " + incoming;
    }
}

和测试代码的Tester类

public class Tester
{

    public static void main(final String[] args) throws InterruptedException
    {
        for (int i = 0; i < 3; i++) {
            final MyClassLoader mcl = new MyClassLoader();
            final String s = mcl.invoke("Bus", "connection", "awesome");
            System.out.println("Tester: " + s);
            Thread.sleep(300);
        }
    }
}

问题:为什么MyClassLoader中的sysout总是打印相同的对象(a.k.a类加载器)?我做错了什么?

我想要实现的是Tester类中的每次迭代,我希望将Bus类加载到新的类加载器中

2 个答案:

答案 0 :(得分:2)

您的自定义类加载器MyClassLoader使用loadClass(String className)的{​​{1}}方法。java.lang.ClassLoader loadClass方法的工作原理是委派,唯一性和可见性。首先你的自定义ClassLoader检查父classLoader是否已经加载了类。由于你还没有定义MyClassLoader的父classLoader,它需要{{1}使用MyClassLoader的getSystemClassLoader()。所以实际上,你的类被SystemClassLoader加载,所有的对象都由一个Classloader加载。通过唯一性原则,每个类都是仅由父母或其自身加载一次。

http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#ClassLoader()

您的MyClassLoader目前如何运作: -

SystemClassLoader

使用java.lang.ClassLoader加载类

public class MyClassLoader extends ClassLoader { //supplied by compiler public MyClassLoader(){ super(); } } 的默认构造函数
java.lang.ClassLoader
java.lang.ClassLoader

SystemClassLoader方法: -

   protected ClassLoader() {

      this.parent = getSystemClassLoader();
      initialized = true;
    }

答案 1 :(得分:1)

您需要实现自己的类加载器,而不是仅使用System类加载器。这是一种相当简单的方法,只有在类文件位于预期目录中时才有效。

public class MyClassLoader extends ClassLoader
{
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        try {
            byte b[] = Files.readAllBytes(Paths.get("target/classes/"+name+".class"));
            ByteBuffer bb = ByteBuffer.wrap(b); 
            return super.defineClass(name, bb,null);
        } catch (IOException ex) {
            return super.loadClass(name);
        }
    }


    public String invoke(final String className, final String methodName, final String someString)
    {
        try {
            final ClassLoader classLoader = this;

...