我在 2009 年 9 月 28 日提交了以下错误。遗憾的是,我仍然没有得到任何回应,并且规范的最终版本仍然不正确。这真的是一个错误吗?如果没有,为什么不呢?如果是,我该怎么办?
包含错误的部分是 5.4.5
(Method overriding): http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.4.5 结合 INVOKEVIRTUAL
操作码的描述:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokevirtual
根据 5.4.5 m1
可以覆盖 m2
即使 m1
是私有(private)的。如果手动创建 .class
文件或组合来自两个编译的 .class
文件,就会发生这种情况。
在我的示例中,我有 A
和 B
类和 B extends A
。我编译了这些类,以便 A
包含一个名为 public
的 f
方法,B
包含一个 private
方法,也名为 f
(通过首先声明这两个方法 public
,编译,将 A.class
复制到安全的地方,删除 f
和A
中的 private
,然后编译 B
并使用 B
的保存版本)。
现在运行它时,我当前的 Oracle JVM 输出 A.class
(意味着调用 A
中的 f
方法)。根据规范,A
应该是输出(意味着应该调用 B
中的 f
方法)。
编辑:实际上, B
应该解决。如果调用者不是 B.f
,则调用可能会由于对已解析方法的访问权限检查而失败。但是,我认为方法解析部分是错误的。
我认为 B
中的定义应该检查 5.4.5
的访问权限,而不仅仅是 m1
。
public class A {
public void f();
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String A
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
public class B extends A {
private void f();
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String B
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
谢谢,
卡斯腾
最佳答案
你的问题,终于解决了。 current version of the Java 8 JVM specification 包含所需的说明:
在第 4.10.1.5 节“类型检查抽象和本地方法”中还有一个补充:
修复时间不到五年,与其他一些问题相比,这很快……
关于jvm - Java 虚拟机规范 (JVMS) : Bug in "5.4.5 Method overriding",我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14753386/