当我运行以下Java代码时:
ClassLoader c = new ClassLoader() {
@Override
public Class<?> findClass(String name) {
return Object.class;
}
};
Class<?> cc = c.loadClass(Object[][].class.getName());
System.out.println(cc.getName());
即使我在代码中将java.lang.Object
替换为Object[][].class.getName()
,我也会在显示终端中获得[[Ljava.lang.Object
。问题是我希望控制台显示[[Ljava.lang.Object
。
实际上,在JVM specification中,我可以阅读以下内容:
数组类由Java虚拟机(第5.3.3节)直接创建,而不是由类加载器创建。但是,D的定义类加载器用于创建数组类C的过程。
由于Object[][]
是一个数组类,我假设我的findClass
不会使用参数[[Ljava.lang.Object
调用,而是使用其元素类型java.lang.Object
。
此外,在“创建数组类”一节中,实际描述了递归算法:
如果组件类型是引用类型,则使用类加载器L递归应用本节(第5.3节)的算法以加载,从而创建C的组件类型。
所以我的问题是:
答案 0 :(得分:4)
您正在询问JVM规范,但您的测试演示了POST /query
的行为,java.lang.ClassLoader
是一个独立的类"invoked by the Java virtual machine to resolve class references"。如果JVM正在加载数组类,它将完全绕过类加载器。这可以通过让JVM尝试使用自定义类加载器加载类来证明:
Class<?> clazz = Class.forName("[[Lcom.foo.Test;", true, new ClassLoader() {
@Override
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
System.out.println("Loading " + name);
return super.loadClass(name, resolve);
}
});
System.out.println(clazz);
输出:
Loading com.foo.Test class [[Lcom.foo.Test;
如您所见,组件类型最初是通过类加载器加载的,但是数组类型是隐式加载的。