我遇到了以下奇怪的Java/JVM规范不完整的情况.假设我们有类(我们将使用Java 1.8和HotSpot):
public class Class {
public static void foo() {
System.out.println("hi");
}
}
public class User {
public static void main(String[] args) {
Class.foo();
}
}
Run Code Online (Sandbox Code Playgroud)
然后重新编译Class to be an interface without recompiling theUser`:
public interface Class {
public static void foo() {
System.out.println("hi");
}
}
Run Code Online (Sandbox Code Playgroud)
运行User.mainnow会产生相同的输出hi.这似乎是显而易见的,但我希望它会失败,IncompatibleClassChangeError这就是为什么:
我知道根据JVM 5.3.5#3语句将类更改为接口是二进制不兼容:
如果命名为C的直接超类的类或接口实际上是一个接口,则加载会抛出一个
IncompatibleClassChangeError.
但是我们假设我们没有继承者Class.我们现在必须参考JVM规范来了解方法的分辨率.第一个版本被编译成这个字节码:
public static void main(java.lang.String[]);
Code:
0: invokestatic #2 // Method examples/Class.foo:()V
3: return
Run Code Online (Sandbox Code Playgroud)
所以我们这里有一个叫做 …