什么是 Java 字节码?
Java 字节码是 Java 源代码(.java
)编译后生成的中间代码(.class
文件),格式为二进制指令集。
特点:
- 与平台无关,通过 JVM(Java 虚拟机) 解释或编译为机器码执行。
- 采用栈式架构(操作数栈存储临时数据),而非寄存器架构
字节码的作用
- 跨平台核心:实现“Write Once, Run Anywhere”,由 JVM 屏蔽底层硬件差异。
- 安全验证:JVM 在加载类时会验证字节码的合法性,防止恶意代码执行。
- 优化基础:JIT 编译器(如 HotSpot)将高频执行的字节码编译为本地机器码,提升性能。
字节码的组成
一个 .class
文件包含以下核心部分(通过 javap
反编译可查看):
结构 | 说明 |
---|---|
魔数(Magic Number) | 标识文件类型(CA FE BA BE ) |
常量池(Constant Pool) | 存储字面量、符号引用等元数据 |
访问标志(Access Flags) | 类的修饰符(如 public ) |
字段表(Field) | 类中定义的字段信息 |
方法表(Methods) | 方法名、参数、字节码指令 |
属性表(Attributes) | 附加信息(如源码行号映射) |
示例:
java
|
|
- 执行命令
javac Bytecode.java
,编译Bytecode.java
文件生成Bytecode.class
文件 - 执行命令
javap -c Bytecode.class
查看反编译后的字节码:
shell
|
|
完整指令集介绍请参考:The Java Virtual Machine Instruction Set —— ORACLE
字节码意义
- 语言无关性:其他 JVM 语言(如 Kotlin、Scala 等)也可编译为字节码运行。
- 性能分析:通过字节码分析程序行为(如方法调用次数、循环复杂度)。
- 动态编程:实现热部署、代码增强(如 Spring AOP 的代理机制)。
字节码操作工具
目前有几种常用的字节码操作工具:
- ASM:直接操作字节码的底层库(用于 AOP、动态代理等)。
- Javassist:通过高级 API 修改字节码(适合动态生成类)。
- Byte Buddy:简化字节码生成的现代库(替代 CGLIB)。
ASM
Maven 依赖: ASM 9.8
xml
|
|
Javassist
Maven 依赖: Javassist 3.30.2-GA
xml
|
|
Byte Buddy
Maven 依赖: Byte Buddy 1.17.5
xml
|
|
JDK 版本与字节码版本对照表
Java 版本 / JDK 版本 | 字节码版本 (major.minor) | 十六进制表示 (major minor) |
---|---|---|
Java 1.1 / JDK 1.1 | 45.3 | 0x2D (45) 0x03 (3) |
Java 1.2 / JDK 1.2 | 46.0 | 0x2E (46) 0x00 (0) |
Java 1.3 / JDK 1.3 | 47.0 | 0x2F (47) 0x00 (0) |
Java 1.4 / JDK 1.4 | 48.0 | 0x30 (48) 0x00 (0) |
Java 5 (1.5) / JDK 5 | 49.0 | 0x31 (49) 0x00 (0) |
Java 6 (1.6) / JDK 6 | 50.0 | 0x32 (50) 0x00 (0) |
Java 7 (1.7) / JDK 7 | 51.0 | 0x33 (51) 0x00 (0) |
Java 8 (1.8) / JDK 8 | 52.0 | 0x34 (52) 0x00 (0) |
Java 9 / JDK 9 | 53.0 | 0x35 (53) 0x00 (0) |
Java 10 / JDK 10 | 54.0 | 0x36 (54) 0x00 (0) |
Java 11 / JDK 11 | 55.0 | 0x37 (55) 0x00 (0) |
Java 12 / JDK 12 | 56.0 | 0x38 (56) 0x00 (0) |
Java 13 / JDK 13 | 57.0 | 0x39 (57) 0x00 (0) |
Java 14 / JDK 14 | 58.0 | 0x3A (58) 0x00 (0) |
Java 15 / JDK 15 | 59.0 | 0x3B (59) 0x00 (0) |
Java 16 / JDK 16 | 60.0 | 0x3C (60) 0x00 (0) |
Java 17 / JDK 17 | 61.0 | 0x3D (61) 0x00 (0) |
Java 18 / JDK 18 | 62.0 | 0x3E (62) 0x00 (0) |
Java 19 / JDK 19 | 63.0 | 0x3F (63) 0x00 (0) |
Java 20 / JDK 20 | 64.0 | 0x40 (64) 0x00 (0) |
Java 21 / JDK 21 | 65.0 | 0x41 (65) 0x00 (0) |
Java 22 / JDK 22 | 66.0 | 0x42 (66) 0x00 (0) |
使用 javap
命令查看 .class
文件的字节码版本:
shell
|
|
说明:如果 Windows 没有安装 grep
相关工具,可使用自带的 findstr
命令替代 grep
感谢您的耐心阅读!来选个表情,或者留个评论吧!