我在2009年9月28日提交了以下错误。遗憾的是,我仍然没有得到任何回复,规范的最终版本仍然不正确。这真的是个bug吗?如果没有,为什么不呢?如果是,我该怎么办?
包含错误的部分是5.4.5
(方法重写):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
。如果手动创建.class
文件或合并两个编辑中的.class
,则会发生这种情况。
在我的示例中,我有A
和B
B extends A
。我编译了这些类,以便A
包含名为public
的{{1}}方法,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
。
m2
谢谢, 卡斯滕
答案 0 :(得分:1)
最后,您的问题已得到解决。 current version of the Java 8 JVM specification包含所需的说明:
5.4.5覆盖
在C类中声明的实例方法m C 会覆盖另一个实例方法m A 在A类中声明如果m C 与m A 相同,或者所有以下都是真的:
- C是A的子类。
- m C 与m A 具有相同的名称和描述符。
- m C 未标记为ACC_PRIVATE。
- 以下之一是真的:
- m A 标记为ACC_PUBLIC;或标记为ACC_PROTECTED;或者没有标记 ACC_PUBLIC或ACC_PROTECTED也不是ACC_PRIVATE和A属于同一个 运行时包为C。
- m C 覆盖方法m'(m'与m C 和m A 不同),使m'覆盖m A 子>
§4.10.1.5“类型检查抽象和本地方法”还有另外一个补充:
私有方法和静态方法与动态方法调度正交, 所以他们永远不会覆盖其他方法(§5.4.5)。
修复不到五年,与其他一些问题相比,这个问题很快......