跳到正文
Elaine Blog
返回

Class 文件、常量池与字节码指令

JVM 与性能

Class 文件是 JVM 的可执行输入,不只是“编译后的二进制”。本教程带你编译一个小类,并用 JDK 自带的 javap 把 常量池、方法描述符和字节码逐项对应到源码。

Table of contents

Open Table of contents

准备并编译样例

下载字节码样例下载, 在实验室根目录运行:

mvn clean compile
javap -classpath target/classes -c -p -s -v dev.elaine.jvmlab.BytecodeSample > bytecode.txt

打开 bytecode.txt,先确认文件头:

magic: 0xCAFEBABE
major version: 65

Java 21 的 Class 主版本是 65;Java 25 是 69。旧 JVM 遇到更高版本会抛出 UnsupportedClassVersionError。修复方法是 使用匹配运行时,或用 --release 重新编译到目标版本,而不是手工改 Class 文件版本号。

读取常量池

**常量池(Constant Pool)**保存数字、字符串、类名,以及字段和方法的符号引用。字节码通常通过索引引用这些项:

#7 = Methodref ... java/io/PrintStream.println:(I)V

(I)V 是方法描述符:接收一个 int,返回 void。符号引用在加载和链接过程中解析为运行时可用结构。常量池不等于 字符串驻留池,两者用途和生命周期不同。

手工走一遍求和字节码

sumTo(int) 的关键指令类似:

iconst_0
istore_1
iconst_1
istore_2
iload_2
iload_0
if_icmpgt ...
iinc 1, 1
iinc 2, 1
goto ...
iload_1
ireturn

局部变量槽 0 保存参数 upperBound,槽 1 保存 total,槽 2 保存循环变量。iload 把值压入操作数栈,比较指令弹出 两个值,ireturn 返回栈顶整数。

字节码是基于栈的指令集,不直接对应 CPU 寄存器。解释器执行它,JIT 也可以把热点路径改写成完全不同的机器码。

使用字节码定位问题

字节码分析适合确认这些问题:

Java 25 的Class 文件规范是字段含义的权威来源。

下一步

阅读解释执行、JIT、分层编译与反优化,观察字节码如何变成热点 机器码。


分享这篇文章:

上一篇
对象创建、布局、逃逸分析与分配路径
下一篇
解释执行、JIT、分层编译与反优化