Java字節(jié)碼文件(.class)的組成圖文詳解
字節(jié)碼文件由五部分組成,分別是基礎(chǔ)信息、常量池、字段、方法、屬性。
案例:
public class Main implements InterfaceA {
public static final String HELLO = "hello";
public static final String WORLD = "world";
public static final String HELLO2 = "hello";
public static final String hello = "hello";
public void methodA() {
String all = HELLO + WORLD;
System.out.println(all);
}
public static void main(String[] args) {
Main main = new Main();
main.methodA();
}
}以下將以上述內(nèi)容為案例,說(shuō)明字節(jié)碼文件的五部分內(nèi)容。
基礎(chǔ)信息
基礎(chǔ)信息中包含魔數(shù)、字節(jié)碼文件對(duì)應(yīng)的 Java 版本號(hào)、訪問(wèn)標(biāo)識(shí)(public、final 等等)及父類和接口。
- 魔數(shù):魔數(shù)用于標(biāo)識(shí)當(dāng)前文件是 java 語(yǔ)言的字節(jié)碼文件(.class),其固定值為
0xCAFEBABE。 - 主/次版本號(hào):主/次版本號(hào)確定當(dāng)前字節(jié)碼文件對(duì)應(yīng)的 JDK 版本號(hào),用于判斷當(dāng)前字節(jié)碼文件的版本與運(yùn)行該字節(jié)碼文件的 JDK 的版本是否兼容。其中,主版本號(hào)用來(lái)標(biāo)識(shí)大版本號(hào),例如 JDK1.0-1.1 使用了 45.0-45.3,JDK1.2 是 46 之后每升級(jí)一個(gè)大版本就加 1;副版本號(hào)是當(dāng)主版本號(hào)相同時(shí)作為區(qū)分不同版本的標(biāo)識(shí),一般只需要關(guān)心主版本號(hào)。
使用 jclasslib 打開(kāi) Main.class 查看一般信息:

常量池
常量池中保存字符串常量、類或接口名、字段名,這些內(nèi)容主要在字節(jié)碼指令中使用。常量池可以避免內(nèi)容重復(fù)定義,減小 .class 文件的大小,從而達(dá)到節(jié)省空間的目的。
例如,使用 jclasslib 打開(kāi) Main.class 查看常量池中 String 類型的常量發(fā)現(xiàn)只有 3 個(gè):

打開(kāi)這 3 個(gè)常量信息,發(fā)現(xiàn)它們的值分別是 helloworld、hello 和 world:

String 類型的常量只有 3 個(gè)而不是 5 個(gè)的原因是成員變量 HELLO、HELLO2 與 hello 都指向常量池中的同一個(gè)值 hello。
需要注意的是,類實(shí)現(xiàn)的接口信息也存放于常量池中:

字段
字段中包含當(dāng)前類或接口聲明的字段信息。
使用 jclasslib 打開(kāi) Main.class 可以查看定義了 4 個(gè)字段信息:

而其中 3 個(gè)指向了常量池中的同一個(gè)值為 hello 的地址:

即上文提到的常量池避免內(nèi)容重復(fù)定義。
方法
方法中包含當(dāng)前類或接口聲明的方法信息。
使用 jclasslib 打開(kāi) Main.class 查看方法信息:

屬性
屬性中包含類的屬性,比如源碼的文件名、內(nèi)部類的列表等。
使用 jclasslib 打開(kāi) Main.class 查看屬性信息:

字節(jié)碼文件內(nèi)容說(shuō)明案例
以上述 Main.java 編譯后的字節(jié)碼文件 Main.class 為例,通過(guò) javap -v Main.class > Main.class.txt 得到 Main.class.txt。
Main.class.txt 內(nèi)容如下:
Classfile /home/wftapp/test/Main.class
Last modified Aug 6, 2025; size 814 bytes
MD5 checksum ccde33e85e9b2fe106990c9f5c38f6bc
Compiled from "Main.java"
public class Main implements InterfaceA
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #8.#33 // java/lang/Object."<init>":()V
#2 = Class #34 // Main
#3 = String #35 // helloworld
#4 = Fieldref #36.#37 // java/lang/System.out:Ljava/io/PrintStream;
#5 = Methodref #38.#39 // java/io/PrintStream.println:(Ljava/lang/String;)V
#6 = Methodref #2.#33 // Main."<init>":()V
#7 = Methodref #2.#40 // Main.methodA:()V
#8 = Class #41 // java/lang/Object
#9 = Class #42 // InterfaceA
#10 = Utf8 HELLO
#11 = Utf8 Ljava/lang/String;
#12 = Utf8 ConstantValue
#13 = String #17 // hello
#14 = Utf8 WORLD
#15 = String #43 // world
#16 = Utf8 HELLO2
#17 = Utf8 hello
#18 = Utf8 <init>
#19 = Utf8 ()V
#20 = Utf8 Code
#21 = Utf8 LineNumberTable
#22 = Utf8 LocalVariableTable
#23 = Utf8 this
#24 = Utf8 LMain;
#25 = Utf8 methodA
#26 = Utf8 all
#27 = Utf8 main
#28 = Utf8 ([Ljava/lang/String;)V
#29 = Utf8 args
#30 = Utf8 [Ljava/lang/String;
#31 = Utf8 SourceFile
#32 = Utf8 Main.java
#33 = NameAndType #18:#19 // "<init>":()V
#34 = Utf8 Main
#35 = Utf8 helloworld
#36 = Class #44 // java/lang/System
#37 = NameAndType #45:#46 // out:Ljava/io/PrintStream;
#38 = Class #47 // java/io/PrintStream
#39 = NameAndType #48:#49 // println:(Ljava/lang/String;)V
#40 = NameAndType #25:#19 // methodA:()V
#41 = Utf8 java/lang/Object
#42 = Utf8 InterfaceA
#43 = Utf8 world
#44 = Utf8 java/lang/System
#45 = Utf8 out
#46 = Utf8 Ljava/io/PrintStream;
#47 = Utf8 java/io/PrintStream
#48 = Utf8 println
#49 = Utf8 (Ljava/lang/String;)V
{
public static final java.lang.String HELLO;
descriptor: Ljava/lang/String;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: String hello
public static final java.lang.String WORLD;
descriptor: Ljava/lang/String;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: String world
public static final java.lang.String HELLO2;
descriptor: Ljava/lang/String;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: String hello
public static final java.lang.String hello;
descriptor: Ljava/lang/String;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: String hello
public Main();
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 1: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LMain;
public void methodA();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: ldc #3 // String helloworld
2: astore_1
3: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
6: aload_1
7: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
10: return
LineNumberTable:
line 12: 0
line 13: 3
line 14: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this LMain;
3 8 1 all Ljava/lang/String;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: new #2 // class Main
3: dup
4: invokespecial #6 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #7 // Method methodA:()V
12: return
LineNumberTable:
line 17: 0
line 18: 8
line 19: 12
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 args [Ljava/lang/String;
8 5 1 main LMain;
}
SourceFile: "Main.java"
Main.class.txt 的各個(gè)組成部分的詳細(xì)解釋如下。
文件基本信息
Classfile /home/wftapp/test/Main.class Last modified Aug 6, 2025; size 814 bytes MD5 checksum ccde33e85e9b2fe106990c9f5c38f6bc Compiled from "Main.java"
- Classfile:指定了字節(jié)碼文件的路徑。
- Last modified:文件的最后修改時(shí)間。
- size:文件的大小,單位是字節(jié)。
- MD5 checksum:文件的 MD5 校驗(yàn)和,用于驗(yàn)證文件的完整性。
- Compiled from:該字節(jié)碼文件是由哪個(gè) Java 源文件編譯而來(lái)的。
類的基本信息
public class Main implements InterfaceA minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER
- public class Main implements InterfaceA:聲明了一個(gè)公共類
Main,該類實(shí)現(xiàn)了接口InterfaceA。 - minor version:次要版本號(hào),這里是 0。
- major version:主要版本號(hào),52 對(duì)應(yīng) Java 8。
- flags:類的訪問(wèn)標(biāo)志,
ACC_PUBLIC表示該類是公共的,ACC_SUPER是一個(gè)歷史遺留標(biāo)志,現(xiàn)代 Java 編譯器都會(huì)設(shè)置這個(gè)標(biāo)志。
常量池
Constant pool: #1 = Methodref #8.#33 // java/lang/Object."<init>":()V #2 = Class #34 // Main #3 = String #35 // helloworld ...
常量池是字節(jié)碼文件的重要組成部分,它包含了類、方法、字段等的符號(hào)引用和字面量。每個(gè)常量都有一個(gè)唯一的索引,通過(guò)這些索引可以在字節(jié)碼中引用常量。例如,#1 是一個(gè)方法引用,指向 java/lang/Object 類的構(gòu)造方法。
字段信息
{
public static final java.lang.String HELLO;
descriptor: Ljava/lang/String;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: String hello
public static final java.lang.String WORLD;
...
聲明了幾個(gè)公共靜態(tài)常量字段,如 HELLO、WORLD 等。
- descriptor:字段的類型描述符,
Ljava/lang/String;表示該字段是String類型。 - flags:字段的訪問(wèn)標(biāo)志,
ACC_PUBLIC表示公共的,ACC_STATIC表示靜態(tài)的,ACC_FINAL表示常量。 - ConstantValue:常量字段的值,這里
HELLO的值是"hello"。
構(gòu)造方法
public Main();
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 1: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LMain;
- public Main():公共的無(wú)參構(gòu)造方法。
- descriptor:方法的描述符,
()V表示該方法沒(méi)有參數(shù),返回值為void。 - flags:方法的訪問(wèn)標(biāo)志,
ACC_PUBLIC表示公共的。 - Code:方法的字節(jié)碼指令,這里調(diào)用了父類
Object的構(gòu)造方法。 - LineNumberTable:行號(hào)表,用于將字節(jié)碼指令與源文件的行號(hào)對(duì)應(yīng)起來(lái)。
- LocalVariableTable:局部變量表,記錄了方法中局部變量的信息,這里
this是Main類的實(shí)例。
實(shí)例方法
public void methodA();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: ldc #3 // String helloworld
2: astore_1
3: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
6: aload_1
7: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
10: return
LineNumberTable:
line 12: 0
line 13: 3
line 14: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this LMain;
3 8 1 all Ljava/lang/String;
- public void methodA():公共的實(shí)例方法,沒(méi)有參數(shù),返回值為
void。 - Code:方法的字節(jié)碼指令,這里將字符串
"helloworld"壓入棧,然后調(diào)用System.out.println方法打印該字符串。 - LineNumberTable:行號(hào)表,將字節(jié)碼指令與源文件的行號(hào)對(duì)應(yīng)。
- LocalVariableTable:局部變量表,記錄了方法中局部變量的信息,
this是Main類的實(shí)例,all是存儲(chǔ)"helloworld"的局部變量。
主方法
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: new #2 // class Main
3: dup
4: invokespecial #6 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #7 // Method methodA:()V
12: return
LineNumberTable:
line 17: 0
line 18: 8
line 19: 12
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 args [Ljava/lang/String;
8 5 1 main LMain;
- public static void main(java.lang.String[]):Java 程序的入口方法。
- Code:方法的字節(jié)碼指令,這里創(chuàng)建了一個(gè)
Main類的實(shí)例,然后調(diào)用該實(shí)例的methodA方法。 - LineNumberTable:行號(hào)表,將字節(jié)碼指令與源文件的行號(hào)對(duì)應(yīng)。
- LocalVariableTable:局部變量表,記錄了方法中局部變量的信息,
args是命令行參數(shù)數(shù)組,main是Main類的實(shí)例。
源文件信息
SourceFile: "Main.java"
指定了該字節(jié)碼文件對(duì)應(yīng)的源文件名稱。
總結(jié)
到此這篇關(guān)于Java字節(jié)碼文件(.class)組成的文章就介紹到這了,更多相關(guān)Java字節(jié)碼文件.class內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于SpringBoot+Redis實(shí)現(xiàn)分布式鎖
本文主要介紹了基于SpringBoot+Redis實(shí)現(xiàn)分布式鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
ExecutorService Callable Future多線程返回結(jié)果原理解析
這篇文章主要為大家介紹了ExecutorService Callable Future多線程返回結(jié)果,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
從內(nèi)存方面解釋Java中String與StringBuilder的性能差異
我們通常會(huì)發(fā)現(xiàn)使用StringBuffer或StringBuilder創(chuàng)建出來(lái)的字符串在拼接時(shí)回避String要來(lái)得快,尤其是StringBuilder,本文就從內(nèi)存方面解釋Java中String與StringBuilder的性能差異,需要的朋友可以參考下2016-05-05
SpringBoot項(xiàng)目構(gòu)建Maven標(biāo)簽及屬性用法詳解
在?Spring?Boot?項(xiàng)目中,Maven?是最常用的構(gòu)建工具之一,本文將詳細(xì)介紹?Maven?依賴管理中的主要標(biāo)簽及其使用方法,幫助開(kāi)發(fā)者更好地理解和使用?Maven?構(gòu)建工具,感興趣的朋友跟隨小編一起看看吧2024-08-08
SpringBoot整合RestTemplate用法的實(shí)現(xiàn)
本篇主要介紹了RestTemplate中的GET,POST,PUT,DELETE、文件上傳和文件下載6大常用的功能,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08
SpringBoot+輕量級(jí)分布式日志框架GrayLog實(shí)踐
將SpringBoot日志遷移至GrayLog的實(shí)戰(zhàn)經(jīng)驗(yàn),稱其配置簡(jiǎn)單、輕量高效,支持多環(huán)境分布式,通過(guò)GELF格式實(shí)現(xiàn)快速日志追蹤與報(bào)警,尤其強(qiáng)調(diào)traceId在跨服務(wù)定位中的關(guān)鍵作用,降低維護(hù)成本并提升故障排查效率2025-08-08
Java 程序設(shè)計(jì)總復(fù)習(xí)題(java基礎(chǔ)代碼)
這篇文章主要介紹了Java 程序設(shè)計(jì)總復(fù)習(xí)題,主要是java基礎(chǔ)代碼,方便學(xué)習(xí)java的同學(xué)2021-05-05

