类路径奇怪的Java类路径/类加载器行为
我在加载一个类文件时有一个非常奇怪的Java类路径行为,该类文件引用了运行时不可用的其他类
如果类路径中只有要加载的类,而该类的方法中没有引用其他类,则加载一个类(在运行时为非接触方法),该类调用另一个类的构造函数,该类的构造函数的参数被强制转换为继承该参数类的类,从而导致parameter类的“未找到类”异常
我正在使用以下java:
java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)
(Windows Server 2008 R2)
以下是一个示例:
public class A
{
public static void main(String[] args)
{
System.out.println("it works");
}
public void foo()
{
new B((D)null);
}
}
public class B
{
public B(C c) {
}
}
public class C
{
}
public class D extends C
{
}
现在我编译这些类,如果我使用类路径中的所有类文件执行类A,它将产生“它可以工作”
如果从类路径中删除除类A以外的所有类,则会发生以下错误:
Exception in thread "main" java.lang.NoClassDefFoundError: C
Caused by: java.lang.ClassNotFoundException: C
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: A. Program will exit.
尽管在运行时永远不需要类C
以下A类星座工程(替换为“新B((D)空)”:
public class A
{
public static void main(String[] args)
{
System.out.println("it works");
}
public void foo()
{
D d = (D)null;
d.toString();
B b = (B)null;
b.toString();
new B(null);
}
}
public class B
{
public B(C c) {
}
}
public class C
{
}
public class D extends C
{
}
以下星座也可以工作(转换为C而不是D;C不继承任何类)
public class A
{
public static void main(String[] args)
{
System.out.println("it works");
}
public void foo()
{
new B((C)null);
}
}
public class B
{
public B(C c) {
}
}
public class C
{
}
public class D extends C
{
}
这是预期的行为还是Java bug
# 1 楼答案
refer section 5.5,如果“如果运行时的值为null,则允许强制转换”,这就是null强制转换工作的原因
# 2 楼答案
我还没有看过JSR,但我猜当解释器解释类文件时,它不会只执行所需的方法,而是会执行所有操作。在这种情况下,需要
A
,如果也解释了foo()
,则需要C
。所有这些都应该在加载A
时发生。因此,错误