在接口的常量池中包含java.lang.Object的目的是什么?

man*_*uti 13 java jvm bytecode interface jvm-hotspot

编译以下界面:

package test;

public interface MyInterface {
    public void foo();
}
Run Code Online (Sandbox Code Playgroud)

并使用javap -v -s test.MyInterface以下方法检查已编译的代码(-s打印成员签名):

  Compiled from "MyInterface.java"
public interface test.MyInterface
  SourceFile: "MyInterface.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
Constant pool:
  #1 = Class              #7              //  test/MyInterface
  #2 = Class              #8              //  java/lang/Object
  #3 = Utf8               foo
  #4 = Utf8               ()V
  #5 = Utf8               SourceFile
  #6 = Utf8               MyInterface.java
  #7 = Utf8               test/MyInterface
  #8 = Utf8               java/lang/Object
{
  public abstract void foo();
    Signature: ()V
    flags: ACC_PUBLIC, ACC_ABSTRACT
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么会出现java.lang.Object在常量池中,知道的接口并没有从继承Object类?

如果我将接口定义更改为:

public interface MyInterface extends Comparable<MyInterface> {
    public void foo();
}
Run Code Online (Sandbox Code Playgroud)

并运行javap,我得到以下内容:

  Compiled from "MyInterface.java"
public interface test.MyInterface extends java.lang.Comparable<test.MyInterface>
  Signature: #7             // Ljava/lang/Object;Ljava/lang/Comparable<Ltest/MyInterface;>;
  SourceFile: "MyInterface.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
  ...
Run Code Online (Sandbox Code Playgroud)

包含java.lang.ObjectLjava/lang/Object;Ljava/lang/Comparable<Ltest/MyInterface;>;界面签名中的目的究竟是什么?

此外,如果我尝试使用工具(特别是JBE)查看字节码,它会错误地显示MyInterface具有保存在常量池中java.lang.Object的类名的超类java.lang.Object:

JBE截图

注意:使用jdk1.7.0_75

Umb*_*ndi 9

Object在常量池类的引用是如何在类文件格式已经在被定义的结果Java虚拟机规范.

类文件由单个ClassFile结构组成:

ClassFile {
    u4             magic;  // The Famous 0xCAFEBABE
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    ...
}
Run Code Online (Sandbox Code Playgroud)

关于这super_class一点,JVM规范的这一部分与您的MyInterface界面相关:

super_class

对于接口,super_class项的值必须始终是constant_pool表的有效索引.该索引处的constant_pool条目必须是CONSTANT_Class_info表示该类的结构Object.

基本上,java/lang/Object只需要super_class使用有效值填充项目,就需要该常量.所有Java实例始终是基本Object类的实例,但这次真正的答案更多地与JVM的构建方式有关,而与具体的实现选择有关,而不是与语言本身有关.

另外,如@Holger所述,这一段也值得一提:

如果super_classitem 的值为零,则此类文件必须表示类Object,唯一没有直接超类的类或接口.

  • 我怀疑这是在将接口改进语言时引入的历史疣,这在1.0中是不可用的. (3认同)
  • 它也符合表示`java/lang/Object`的类文件是没有`super_class`值的*only*类文件的说法.这可能会让事情变得更容易 (2认同)