Java 关于用 Java 14 生成的 .class 的问题

Java question about a .class generated with Java 14

我有一个简单的 class 像这样:

class ClassWithDefaultConstructor{}

我正在使用这个 JDK:

C:\JavaSE14Folder>java -version
java version "14" 2020-03-17
Java(TM) SE Runtime Environment (build 14+36-1461)
Java HotSpot(TM) 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)

如您所见,我使用的是最新版本的 JDK。

我创建这个 .class 是这样的:

C:\JavaSE14Folder>javac -d . ClassWithDefaultConstructor.java

稍后创建.class 我尝试这个命令:

C:\JavaSE14Folder>javap ClassWithDefaultConstructor.class

我看到了以下内容:

Compiled from "ClassWithDefaultConstructor.java"
class ClassWithDefaultConstructor {
   ClassWithDefaultConstructor();
}

这里有两件事让我很开心;首先创建默认构造函数,我看到构造函数的可见性与 class 相同,但有三件事让我感到难过。

我的问题是:

  1. 为什么构造函数没有主体并以;终止?
  2. 为什么构造函数没有调用 java.lang.Object 构造函数?
  3. 为什么这个 class 没有扩展 java.lang.Object

我确实期待这样的事情:

class ClassWithDefaultConstructor extends java.lang.Object {
   ClassWithDefaultConstructor(){
       super();
   }
}

我期待这样的字节码 post:

Post

我是不是漏掉了什么?

如果我这样输入命令:

C:\JavaSE14Folder>javap -c ClassWithDefaultConstructor.class
Compiled from "ClassWithDefaultConstructor.java"
class ClassWithDefaultConstructor {
 ClassWithDefaultConstructor();
 Code:
   0: aload_0
   1: invokespecial #1                  // Method java/lang/Object." 
<init>":
()V
   4: return
}

不同,但我仍然没有看到我的东西,比如扩展对象等等。

我希望至少在 post:

中看到这样的东西
Compiled from "test.java"
public class test extends java.lang.Object{

总而言之,我没有看到编译器插入那些隐式行。

在此 中声明在 Java.

的较新版本上发生相同的情况

相同的输出使用:

C:\Program Files\Java\jdk1.8.0_121\bin

字节码 != Java 源代码。

类文件中实际上只是随机字节。您看到的是 javap 字节码的文本表示,它旨在让 Java 不太了解字节码的程序员熟悉,因此使用 Java 语法在可能的情况。但它不是也不意味着是实际的 Java 源代码。

如果您使用不同的反汇编程序,例如 Krakatau,输出看起来会非常不同,但它仍然是相同二进制类文件的表示。

来自 javapdocumentation:
"javap 命令反汇编一个或多个 class 文件。"

它不会反编译 class 文件,也就是说,它不会创建有效的 java 源代码。

"1.为什么构造函数没有body,以;?结束"
它不是反编译代码,无效 Java,只是一个 指示 有这样的构造函数。

"2.为什么构造函数没有调用java.lang.Object构造函数?"
它被 javap 省略了,但它在那里,如果使用了正确的选项就会显示(见下文)。

"3. 为什么这个 class 没有扩展 java.lang.Object?"
和之前一样,只是 javap.

没有显示

要查看更多详细信息,我们必须将 -v(详细)选项添加到 javap 调用中。如果使用 javap -c -v ClassWithDefaultConstructor(我添加的行号),这里的输出是:

1   Classfile /C:/tmp/ClassWithDefaultConstructor.class
2     Last modified 16 Jan 2022; size 228 bytes
3     SHA-256 checksum 101973fdf86b3e7facf263214f6932a9353ef7be914efec9963be3a578b3ddaf
4     Compiled from "ClassWithDefaultConstructor.java"
5   class ClassWithDefaultConstructor
6     minor version: 0
7     major version: 61
8     flags: (0x0020) ACC_SUPER
9     this_class: #7                          // ClassWithDefaultConstructor
10    super_class: #2                         // java/lang/Object
11    interfaces: 0, fields: 0, methods: 1, attributes: 1
12  Constant pool:
13     #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
14     #2 = Class              #4             // java/lang/Object
15     #3 = NameAndType        #5:#6          // "<init>":()V
16     #4 = Utf8               java/lang/Object
17     #5 = Utf8               <init>
18     #6 = Utf8               ()V
19     #7 = Class              #8             // ClassWithDefaultConstructor
20     #8 = Utf8               ClassWithDefaultConstructor
21     #9 = Utf8               Code
22    #10 = Utf8               LineNumberTable
23    #11 = Utf8               SourceFile
24    #12 = Utf8               ClassWithDefaultConstructor.java
25  {
26    ClassWithDefaultConstructor();
27      descriptor: ()V
28      flags: (0x0000)
29      Code:
30        stack=1, locals=1, args_size=1
31           0: aload_0
32           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
33           4: return
34        LineNumberTable:
35          line 1: 0
36  }
37  SourceFile: "ClassWithDefaultConstructor.java"

第 10 行:super_class: #2 // java/lang/Object
给我们超级 class,即 Object

第 32 行: 1: invokespecial #1 // Method java/lang/Object."<init>":()V
这是为实际实例调用 Object 的构造函数(前一行 aload_0=this) - <init> 是用于构造函数的名称(独立于 class name) - 相当于 super().