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 相同,但有三件事让我感到难过。
我的问题是:
- 为什么构造函数没有主体并以
;
终止?
- 为什么构造函数没有调用 java.lang.Object 构造函数?
- 为什么这个 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,输出看起来会非常不同,但它仍然是相同二进制类文件的表示。
来自 javap
的 documentation:
"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()
.
我有一个简单的 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 相同,但有三件事让我感到难过。
我的问题是:
- 为什么构造函数没有主体并以
;
终止? - 为什么构造函数没有调用 java.lang.Object 构造函数?
- 为什么这个 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{
总而言之,我没有看到编译器插入那些隐式行。
在此
相同的输出使用:
C:\Program Files\Java\jdk1.8.0_121\bin
字节码 != Java 源代码。
类文件中实际上只是随机字节。您看到的是 javap
字节码的文本表示,它旨在让 Java 不太了解字节码的程序员熟悉,因此使用 Java 语法在可能的情况。但它不是也不意味着是实际的 Java 源代码。
如果您使用不同的反汇编程序,例如 Krakatau,输出看起来会非常不同,但它仍然是相同二进制类文件的表示。
来自 javap
的 documentation:
"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()
.