如何看懂Java字节码关键字
1. 类与方法结构相关
public class com/mozi/Main
- 作用:定义类的全限定名(含包路径)。
- 格式:
public class <包名>/<类名>。
// access flags 0x21
- 作用:类的访问修饰符标志(十六进制)。
0x21=0x20 (ACC_SUPER)+0x1 (ACC_PUBLIC)。ACC_SUPER是历史遗留标志,现代 Java 默认启用。
public <init>()V
- 作用:构造函数的方法定义。
<init>是 JVM 内部约定的构造函数方法名。()V表示无参且返回类型为void。
public static main([Ljava/lang/String;)V
- 作用:
main方法的定义。[Ljava/lang/String;是String[]的类型描述符。V表示返回类型为void。
2. 数据加载与存储
ALOAD / ILOAD / …
作用:从局部变量表加载数据到操作数栈。
- 前缀:
A(对象引用)、I(整型)、F(浮点)、D(双精度)、L(长整型)。 - 后缀:数字表示局部变量索引(如
ALOAD 0加载this)。
- 前缀:
示例:
1
2ALOAD 0 // 加载局部变量槽 0(this 引用)
ILOAD_1 // 加载局部变量槽 1 的 int 值(短格式,索引 1)
ASTORE / ISTORE / …
作用:将操作数栈顶的值存储到局部变量表。
- 前缀与
LOAD相同。
1
2ASTORE 1 // 将栈顶的对象引用存入局部变量槽 1
ISTORE_2 // 将栈顶的 int 值存入局部变量槽 2- 前缀与
3. 操作数栈操作
DUP
- 作用:复制栈顶的值。
- 栈变化:
..., value → ..., value, value。 - 用途:常用于对象初始化(如
new后调用构造函数前保留对象引用)。
- 栈变化:
POP
- 作用:丢弃栈顶的值。
- 栈变化:
..., value → ...。
- 栈变化:
SWAP
- 作用:交换栈顶两个值的位置。
- 栈变化:
..., value1, value2 → ..., value2, value1。
- 栈变化:
4. 对象与数组操作
NEW
作用:创建新对象(但未初始化)。
示例:
1
NEW java/lang/StringBuilder
栈变化:
... → ..., objectRef(未初始化的对象引用)。
ANEWARRAY
作用:创建引用类型数组。
参数:数组元素的类型(如
java/lang/String)。栈输入:数组长度(
int)。栈输出:数组引用。
示例:
1
2ICONST_2
ANEWARRAY java/lang/String // 创建 String[2]
AASTORE / IASTORE / …
作用:将值存入数组。
前缀:
A(对象引用)、I(整型)等。栈输入:
arrayRef, index, value。示例:
1
2
3
4DUP // 复制数组引用
ICONST_0 // 索引 0
LDC "add" // 值 "add"
AASTORE // 执行 arrayRef[0] = "add"
5. 方法调用
INVOKESPECIAL
作用:调用构造函数、私有方法或父类方法。
示例:
1
INVOKESPECIAL java/lang/Object.<init> ()V // 调用 Object 的构造函数
INVOKEVIRTUAL
作用:调用实例方法(基于对象实际类型,动态绑定)。
示例:
1
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V // 调用 println
INVOKESTATIC
作用:调用静态方法。
示例:
1
INVOKESTATIC java/util/Arrays.asList ([Ljava/lang/Object;)Ljava/util/List;
INVOKEINTERFACE
作用:调用接口方法。
示例:
1
INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator; (itf)
6. 类型转换与检查
CHECKCAST
作用:检查对象是否为指定类型,否则抛出
ClassCastException。示例:
1
CHECKCAST java/lang/String // 确保栈顶对象是 String
INSTANCEOF
作用:检查对象是否为某类型,结果压入栈(
1或0)。1
INSTANCEOF java/lang/Integer
7. 控制流
IFEQ / IFNE / …
作用:条件跳转。
输入:栈顶的
int值。示例:
1
IFEQ L3 // 如果栈顶值为 0,跳转到标签 L3
GOTO
作用:无条件跳转。
1
GOTO L2 // 跳转到标签 L2
RETURN / IRETURN / ARETURN / …
作用:方法返回。
- 前缀:
V(void)、I(int)、A(对象引用)等。
1
2RETURN // void 方法返回
ARETURN // 返回对象引用- 前缀:
8. 调试信息
LINENUMBER
作用:关联字节码指令与源代码行号。
1
LINENUMBER 17 L0 // 以下指令对应源码第 17 行,标签为 L0
LOCALVARIABLE
作用:定义局部变量的作用域和类型。
1
LOCALVARIABLE s Ljava/lang/String; L4 L5 3 // 变量 s 类型为 String,作用域从 L4 到 L5,存储在槽 3
FRAME
作用:描述当前栈帧的状态(用于调试和验证)。
1
FRAME APPEND [java/util/List java/util/Iterator] // 栈帧追加了 List 和 Iterator 变量
9. 其他关键指令
LDC
作用:从常量池加载常量(字符串、类、数值等)。
1
LDC "add" // 加载字符串 "add"
ICONST / ACONST_NULL / …
作用:将常量压入栈。
示例:
1
2ICONST_0 // 压入 int 0
ACONST_NULL // 压入 null
总结
- 栈操作:字节码指令高度依赖操作数栈(如
DUP、POP)。 - 类型敏感:指令前缀(
A、I、F)严格区分操作的数据类型。 - 符号引用:通过常量池索引(如
#2)引用类、方法、字段等。 - 调试支持:
LINENUMBER和LOCALVARIABLE帮助映射字节码与源码。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Moziの个人博客!
评论
