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

2022-09-04 22:06:14

编译以下接口:

package test;

public interface MyInterface {
    public void foo();
}

并检查编译的代码使用显示以下内容( 打印成员签名):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
}

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

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

public interface MyInterface extends Comparable<MyInterface> {
    public void foo();
}

并运行,我得到以下内容: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
  ...

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

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

JBE screenshot

注意:使用jdk1.7.0_75


答案 1

常量池中的类引用是在 Java VM 规范中定义类文件格式的结果。Object

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

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;
    ...
}

关于这一点,JVM 规范的这一部分与您的接口相关:super_classMyInterface

super_class

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

因此,从本质上讲,只需要用有效值填充项目即可。所有Java实例始终是基本类的实例,但这一次真正的答案更多地与JVM的构建方式和特定的实现选择有关,而不是与语言本身有关。java/lang/Objectsuper_classObject

此外,正如@Holger所指出的,这一段也值得一提:

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


答案 2

实际上,Java中的所有内容都是.在Java中,每个结构都是对象。Object

Class IS Object
Interface IS Object
Enum IS Object.

所以当你构建程序时会自动打包。因为可以在另一个JVM上使用。Object*.class

在这种情况下,@user43250937正确

JVM Spec :

要由 Java 虚拟机执行的已编译代码使用与硬件和操作系统无关的二进制格式表示,该格式通常(但不一定)存储在文件中,称为类文件格式。类文件格式精确定义了类或接口的表示形式,包括字节排序等细节,这些细节在特定于平台的对象文件格式中可能是理所当然的

可能是此链接授予您更多信息。

Java 字节码基本原理使用对象和调用方法

4:  invokeinterface #5,  1; //InterfaceMethod Job.execute:()Ljava/lang/Object;

JVM 规范