我在 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 文件,就会发生这种情况。

在我的示例中,我有 AB 类和 B extends A 。我编译了这些类,以便 A 包含一个名为 publicf 方法,B 包含一个 private 方法,也名为 f(通过首先声明这两个方法 public ,编译,将 A.class 复制到安全的地方,删除 fA 中的 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/

10-10 21:19