gpt4 book ai didi

java - 类级静态 block 是否表示为字节码中的方法?

转载 作者:行者123 更新时间:2023-11-30 08:30:18 26 4
gpt4 key购买 nike

我创建了一个小的 Java 类并对相应的 .class 文件运行了 javap 命令。我这样做只是为了了解类文件的组织方式(是的,我也一直在研究 JVM 规范)。我可能是错的,但根据我对类文件结构的理解。似乎类级静态 block 被列为一种方法。

我的解释是否正确(静态 block 被表示为一种方法)?如果是,静态 block 是否以某种方式被认为等同于 Java 中的方法?

源文件:

package test;

public class TestClass
{
static {
System.out.println("abcd");
}

public void method(String s)
{
System.out.println("hello world");
}
}

javap 输出:

Classfile /C:/TestClass.class
Last modified Dec 25, 2016; size 477 bytes
MD5 checksum 7571c8f98e814fb8bb53885f073c6048
Compiled from "TestClass.java"
public class test.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #7.#17 // java/lang/Object."<init>":()V
#2 = Fieldref #18.#19 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #20 // hello world
#4 = Methodref #21.#22 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = String #23 // abcd
#6 = Class #24 // test/TestClass
#7 = Class #25 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 method
#13 = Utf8 (Ljava/lang/String;)V
#14 = Utf8 <clinit>
#15 = Utf8 SourceFile
#16 = Utf8 TestClass.java
#17 = NameAndType #8:#9 // "<init>":()V
#18 = Class #26 // java/lang/System
#19 = NameAndType #27:#28 // out:Ljava/io/PrintStream;
#20 = Utf8 hello world
#21 = Class #29 // java/io/PrintStream
#22 = NameAndType #30:#13 // println:(Ljava/lang/String;)V
#23 = Utf8 abcd
#24 = Utf8 test/TestClass
#25 = Utf8 java/lang/Object
#26 = Utf8 java/lang/System
#27 = Utf8 out
#28 = Utf8 Ljava/io/PrintStream;
#29 = Utf8 java/io/PrintStream
#30 = Utf8 println
{
public test.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0

public void method(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String hello world
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 11: 0
line 12: 8

static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=2, locals=0, args_size=0
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #5 // String abcd
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 6: 0
line 7: 8
}
SourceFile: "TestClass.java"

最佳答案

Java 中有两种类型的初始化器,实例和静态。

在字节码级别,所有静态初始化器(加上非最终或初始化为非常量表达式的静态字段的初始化)被编译并连接到一个方法中,称为 <clinit> .这是一个特殊的方法,在一个类加载后由JVM自动调用,但不能被普通代码调用。请注意,无论您在源代码级别有多少个单独的静态初始化程序 block ,都只有一个 clinit 方法。

实例初始化器在字节码中没有直接的等价物。所有的实例初始化器,加上实例字段的初始化器,在从父类(super class)构造函数调用返回后立即被编译并插入到类构造函数方法中。顺便说一句,这意味着可以在调用初始化程序之前观察实例的状态,这就是为什么您不应该从构造函数调用虚方法。

关于java - 类级静态 block 是否表示为字节码中的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41318966/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com