考虑自定义类加载器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
。
有人可以解释这个问题吗?
答案 0 :(得分:0)
默认的 public static IMsg Desirialize(MemoryStream ms) // socket buffer
{
ms.Position = 0;
return Serializer.Deserialize<IMsg>(ms);
}
实现按以下顺序执行类加载:
- 调用findLoadedClass(String)来检查该类是否已经 已加载。
- 在父类加载器上调用loadClass方法。如果父级为null,则虚拟机内置的类加载器为 代替。
- 调用findClass(String)方法来查找类。
这是从Javadoc中提取的直接内容。
当调用ClassLoader
时,您的实现将在尝试自身加载之前委派给父类加载器。这恰好是您的系统类加载器。
在这种情况下,您的类已在系统ClassLoader的类路径上,因此已将其加载。
以后再调用loadClass
时,该方法仅检查指定的 ClassLoader是否已加载该类。它不执行进一步的委派。
调用findLoadedClass
时,您正在尝试在method.invoke(loader, "java.util.ArrayList")
中查找已加载的类。这将失败,因为它是由父ClassLoader代替执行加载的。
您可以通过在系统ClassLoader上调用方法来证明这一点,就像这样:
CustomerClassLoader