为什么findLoadedClass方法调用返回不同的结果?

时间:2019-07-29 12:11:53

标签: java classloader

考虑自定义类加载器class CustomClassLoader extends ClassLoader{}

如果我按以下方式致电loadClass

ClassLoader loader = new ClassLoader(){}; 
loader.loadClass("java.util.ArrayList");
Method method = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
method.setAccessible(true);
System.out.println(method.invoke(loader,"java.util.ArrayList"));

它输出null

但是如果我替换

loader.loadClass("java.util.ArrayList"); 

使用

Class.forName("java.util.ArrayList",true,loader);

它输出class java.util.ArrayList

有人可以解释这个问题吗?

1 个答案:

答案 0 :(得分:0)

默认的 public static IMsg Desirialize(MemoryStream ms) // socket buffer { ms.Position = 0; return Serializer.Deserialize<IMsg>(ms); } 实现按以下顺序执行类加载:

  
      
  1. 调用findLoadedClass(String)来检查该类是否已经   已加载。
  2.   
  3. 在父类加载器上调用loadClass方法。如果父级为null,则虚拟机内置的类加载器为   代替。
  4.   
  5. 调用findClass(String)方法来查找类。
  6.   

这是从Javadoc中提取的直接内容。

当调用ClassLoader时,您的实现将在尝试自身加载之前委派给父类加载器。这恰好是您的系统类加载器。

在这种情况下,您的类已在系统ClassLoader的类路径上,因此已将其加载。

以后再调用loadClass时,该方法仅检查指定的 ClassLoader是否已加载该类。它不执行进一步的委派。

调用findLoadedClass时,您正在尝试在method.invoke(loader, "java.util.ArrayList")中查找已加载的类。这将失败,因为它是由父ClassLoader代替执行加载的。

您可以通过在系统ClassLoader上调用方法来证明这一点,就像这样:

CustomerClassLoader