java.lang.Object怎么可能在Java中实现?

How is it possible that java.lang.Object is implemented in Java?

根据 Java Language Specification, java.lang.Object is the root of Java's inheritance hierarchy. Unlike C++ or Objective-C, programmers cannot specify their own root superclasses. Because of this, I figured it was impossible to actually define java.lang.Object in Java itself. To my surprise, I found that OpenJDK indeed has a concrete implementation of java.lang.Object.

我想看看是否可以用 JDK/JRE 1.8 编译和 运行 我自己的 java.lang.Object 版本,所以我写成 Object.java:

package java.lang;
public class Object {
    public static void main(String[] args) {
        System.out.println("Hello world from custom java.lang.Object!");
    }
}

它用 javac 编译得很好,但如果我尝试通过 java -cp . java.lang.Object 执行类文件,JVM 会出错并显示此消息:

Error: Main method not found in class java.lang.Object, please define the main method as:
   public static void main(String[] args)

这表明 JVM 在类路径中使用的是库存 java.lang.Object 而不是 Object.class

是否可以将 Java 中的 java.lang.Object 定义为最终用户?幕后发生了什么?我看到两种可能性:

这是一个非常酷的实验。 但这就是 Java 的工作方式

  1. 由于 Java 中的每个 class 都必须扩展 java.lang.Object,您的自定义 Object class 也会扩展它。
  2. 要加载任何 class,Java 需要加载它的父 class。因此,当 Java 尝试 运行 自定义 Object class 中的 main() 方法时,它会加载真正的 java.lang.Object class。
  3. 一旦真正的 java.lang.Object class 被加载,JVM 就会尝试 运行 class 的 main() 方法。由于它不存在,您的应用程序失败。

可以修改java.lang.Object(例如通过添加public static void main()方法),但是为了被JVM加载和使用,修改后的class 需要添加到 bootstrap class 路径。

在 JDK 8 这可以通过

完成
java -Xbootclasspath/p:<path>

在 JDK 9+ 这需要修补 java.base 模块:

java --patch-module java.base=<path>

当 JVM 启动时,它通过 bootstrap class 加载器加载 java.lang.Object 就像任何其他 class 一样,所以 java.lang.Object 添加了 main方法可以实际执行:

$ java -Xbootclasspath/p:. java.lang.Object
Hello world from custom java.lang.Object!

但是,如果您尝试删除现有的 java.lang.Object 方法、添加新的虚拟方法、添加字段或以其他方式更改现有布局 - 这将不起作用。最有可能的是,JVM 将因致命错误而崩溃。

这是因为 JVM 期望 java.lang.Object 具有已知布局。 JVM源代码中有硬编码的偏移量,对现有方法的引用等。对于其他内部classes也是如此,如java.lang.Stringjava.lang.Classjava.lang.ref.Reference 和类似的。

关于 Object 的 superclass,JVM Specification 中明确描述了一个例外:

If the value of the super_class item is zero, then this class file must represent the class Object, the only class or interface without a direct superclass.

Java 编译器和 JVM 都知道此异常,并在 compiling Object.java and when loading Object.class.

时执行此规则

您可以在 Java 中实现 java.lang.Object 并且您正在使用的实际 class 确实是从 [=82] 附带的 Object.java 文件创建的=].

Java® 语言规范在 Chapter 8. Classes 中说:

Each class except Object is an extension of (that is, a subclass of) a single existing class (§8.1.4) and may implement interfaces (§8.1.5).

因此 Object 的超类型的缺失在语言中是固定的。

您可以使用您实验的源代码并尝试添加 extendsimplements 子句,看看编译器是否会拒绝它。

当您编译 class java.lang.Object 时,生成的 class 文件将是唯一没有超类型的文件。请参阅 Java® 虚拟机规范,§4.1., The ClassFile Structure

super_class

For a class, the value of the super_class item either must be zero or must be a valid index into the constant_pool table. If the value of the super_class item is nonzero, the constant_pool entry at that index must be a CONSTANT_Class_info structure representing the direct superclass of the class defined by this class file. Neither the direct superclass nor any of its superclasses may have the ACC_FINAL flag set in the access_flags item of its ClassFile structure.

If the value of the super_class item is zero, then this class file must represent the class Object, the only class or interface without a direct superclass.

For an interface, the value of the super_class item must always be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure representing the class Object.

因此,即使接口在 class 文件(指向 Object)中也有 superclass 的条目和 java.lang.Object 的 class 文件超级class.

唯一一个零条目

当您尝试在运行时加载您的 Object class 版本时,您偶然发现无法加载 [=37= 的 classes ] 包(或任何限定名称以 java. 开头的 class)通常通过 class 路径。

在 Java9 之前,您必须设置 bootstrap class path to include your version. Starting with Java 9, the class java.lang.Object must belong to the java.base module, which is loaded in an implementation specific manner. You’d have to use the --patch-module 选项来注入您自己的版本。

但是你必须小心你写入自己版本的内容。其他 classes 和环境有很多期望,不满足这些期望可能会(严重)破坏它。

JLS, §4.3.2. The Class Object 列出了预期的方法和指向为其中一些方法定义特殊语言语义的其他章节的链接。