使用自定义 class 加载程序加载静态方法

Loading a static method using custom class loader

我有一个自定义 class 加载程序,如下所示

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

和一个 class 名为 Bus

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

和测试人员 class 来测试代码

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 class loader)?我做错了什么?

我想要实现的是对于测试器 class 中的每次迭代,我希望将总线 class 加载到新的 class 加载器

你的自定义class加载器MyClassLoader使用java.lang.ClassLoaderloadClass(String className)方法。ClassLoaderloadClass方法的工作原理授权、唯一性和可见性。首先,您的自定义 MyClassLoader 检查父 classLoader 是否已经加载了 class 或 not.Since 你还没有定义 MyClassLoader 的父 classLoader,它需要 SystemClassLoader 使用 java.lang.ClassLoader 的 getSystemClassLoader()。 所以实际上,你 classes由 SystemClassLoader 加载,所有对象都由单个类加载器加载。根据唯一性原则,每个 class 只加载一次,由其父级加载或由其自身加载。

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

您的 MyClassLoader 目前如何工作:-

public class MyClassLoader extends ClassLoader
{
//supplied by compiler
   public MyClassLoader(){
   super();
   }
}

java.lang.ClassLoader 的默认构造函数使用 SystemClassLoader 加载 classes

   protected ClassLoader() {

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

loadClass java.lang.ClassLoader 的方法:-

308     protected synchronized Class<?> More ...loadClass(String name, boolean resolve)
309         throws ClassNotFoundException
310     {
311         // First, check if the class has already been loaded
312         Class c = findLoadedClass(name);
313         if (c == null) {
314             try {
315                 if (parent != null) {
316                     c = parent.loadClass(name, false);

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

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;

...