JVM 字节码指令集非常庞大,包含了大量的指令来完成各种操作。 我们只需要掌握一些常用的字节码指令即可。
以下是一些最常用、最核心的 JVM 字节码指令,按照功能类别进行划分:
1. 操作数栈 (Operand Stack) 操作指令:
nop
(No Operation): 什么也不做,空指令,通常用于调试或占位。aconst_null
(Push null): 将 null
引用值推送到操作数栈顶。iconst_m1
, iconst_0
, iconst_1
, iconst_2
, iconst_3
, iconst_4
, iconst_5
(Push int constant): 将 int
型常量 -1, 0, 1, 2, 3, 4, 5
推送到操作数栈顶。fconst_0
, fconst_1
, fconst_2
(Push float constant): 将 float
型常量 0.0f, 1.0f, 2.0f
推送到操作数栈顶。dconst_0
, dconst_1
(Push double constant): 将 double
型常量 0.0d, 1.0d
推送到操作数栈顶。lconst_0
, lconst_1
(Push long constant): 将 long
型常量 0L, 1L
推送到操作数栈顶。bipush
(Push byte): 将 byte
型常量
推送到操作数栈顶。sipush > (Push short):
将 short
型常量 > 推送到操作数栈顶。
ldc
(Load constant): 从常量池中加载 int
, float
, String
类型常量或类引用推送到操作数栈顶。ldc_w
(Load constant wide): 宽索引版本 ldc
,用于加载常量池索引范围更大的常量。ldc2_w
(Load constant wide 2): 从常量池中加载 long
或 double
类型常量推送到操作数栈顶 (占用两个栈槽)。pop
(Pop top operand stack value): 将栈顶数值弹出 (通常用于丢弃不需要的计算结果)。pop2
(Pop top 2 operand stack values): 将栈顶两个数值弹出 (用于 long
和 double
类型,或两个非 long
和 double
类型的值)。dup
(Duplicate top operand stack value): 复制栈顶数值,并将副本压入栈顶。dup_x1
(Duplicate top operand stack value and insert below): 复制栈顶数值,并将副本插入到栈顶数值之下。dup_x2
(Duplicate top operand stack value and insert two values down): 复制栈顶数值,并将副本插入到栈顶数值之下两个位置。dup2
(Duplicate top 1 or 2 operand stack values): 复制栈顶一个或两个数值,并将副本压入栈顶 (用于 long
和 double
或两个非 long
和 double
类型的值)。dup2_x1
(Duplicate top 1 or 2 operand stack values and insert below): 复制栈顶一个或两个数值,并将副本插入到栈顶数值之下。dup2_x2
(Duplicate top 1 or 2 operand stack values and insert two values down): 复制栈顶一个或两个数值,并将副本插入到栈顶数值之下两个位置。swap
(Swap top two operand stack values): 交换栈顶两个数值。2. 局部变量表 (Local Variable Table) 访问指令:
iload
, fload
, aload
, lload
, dload
(Load from local variable): 将指定索引的 int
, float
, reference
, long
, double
型局部变量加载到操作数栈顶。iload_0
, iload_1
, iload_2
, iload_3
(Load int from local variable 0-3): 加载索引为 0, 1, 2, 3
的 int
型局部变量到栈顶 (更高效的指令)。fload_0
, fload_1
, fload_2
, fload_3
(Load float from local variable 0-3): 加载索引为 0, 1, 2, 3
的 float
型局部变量到栈顶。aload_0
, aload_1
, aload_2
, aload_3
(Load reference from local variable 0-3): 加载索引为 0, 1, 2, 3
的 reference
型局部变量到栈顶 (例如 this
引用通常在索引 0)。lload_0
, lload_1
, lload_2
, lload_3
(Load long from local variable 0-3): 加载索引为 0, 1, 2, 3
的 long
型局部变量到栈顶。dload_0
, dload_1
, dload_2
, dload_3
(Load double from local variable 0-3): 加载索引为 0, 1, 2, 3
的 double
型局部变量到栈顶。istore
, fstore
, astore
, lstore
, dstore
(Store into local variable): 将栈顶的 int
, float
, reference
, long
, double
型数值存储到指定索引的局部变量。istore_0
, istore_1
, istore_2
, istore_3
(Store int into local variable 0-3): 将栈顶 int
型数值存储到索引为 0, 1, 2, 3
的局部变量 (更高效的指令)。fstore_0
, fstore_1
, fstore_2
, fstore_3
(Store float into local variable 0-3): 将栈顶 float
型数值存储到索引为 0, 1, 2, 3
的局部变量。astore_0
, astore_1
, astore_2
, astore_3
(Store reference into local variable 0-3): 将栈顶 reference
型数值存储到索引为 0, 1, 2, 3
的局部变量。lstore_0
, lstore_1
, lstore_2
, lstore_3
(Store long into local variable 0-3): 将栈顶 long
型数值存储到索引为 0, 1, 2, 3
的局部变量。dstore_0
, dstore_1
, dstore_2
, dstore_3
(Store double into local variable 0-3): 将栈顶 double
型数值存储到索引为 0, 1, 2, 3
的局部变量。3. 运算指令:
iadd
, fadd
, dadd
, ladd
(加法)isub
, fsub
, dsub
, lsub
(减法)imul
, fmul
, dmul
, lmul
(乘法)idiv
, fdiv
, ddiv
, ldiv
(除法)irem
, frem
, drem
, lrem
(求余数)ineg
, fneg
, dneg
, lneg
(取反)ishl
, lshl
(左移)ishr
, lshr
(算术右移)iushr
, lushr
(逻辑右移)iand
, land
(按位与)ior
, lor
(按位或)ixor
, lxor
(按位异或)iinc
(int 变量自增,局部变量表操作)i2b
, i2c
, i2s
(int 转 byte, char, short)i2l
, i2f
, i2d
(int 转 long, float, double)l2i
, l2f
, l2d
(long 转 int, float, double)f2i
, f2l
, f2d
(float 转 int, long, double)d2i
, d2l
, d2f
(double 转 int, long, float)lcmp
(long 比较)fcmpl
, fcmpg
(float 比较,l
表示 NaN 时结果为 -1,g
表示 NaN 时结果为 1)dcmpl
, dcmpg
(double 比较,l
表示 NaN 时结果为 -1,g
表示 NaN 时结果为 1)4. 类型转换和检查指令:
checkcast
(Check whether object is of given type): 检查对象是否是指定类型,如果是则继续,否则抛出 ClassCastException
。instanceof
(Determine if object is of given type): 检查对象是否是指定类型的实例,结果 (1
或 0
) 推送到操作数栈顶。5. 对象操作指令:
new
(Create new object): 创建一个对象,但不初始化,只在堆上分配空间,并将未初始化的对象引用推送到操作数栈顶。anewarray
(Create new array of references): 创建一个指定组件类型的引用类型数组,数组长度从操作数栈弹出。newarray
(Create new array of primitive type): 创建一个指定基本类型的基本类型数组,数组长度从操作数栈弹出 (例如 int
, boolean
, char
等)。arraylength
(Get length of array): 获取数组长度,数组引用从操作数栈弹出,数组长度推送到栈顶。aaload
, baload
, caload
, saload
, iaload
, laload
, faload
, daload
(Load from array): 从数组中加载元素,数组引用和索引从操作数栈弹出,加载的元素值推送到栈顶 (对应 reference
, byte
, char
, short
, int
, long
, float
, double
类型)。aastore
, bastore
, castore
, sastore
, iastore
, lastore
, fastore
, dastore
(Store into array): 将值存储到数组中,数组引用、索引和要存储的值从操作数栈弹出 (对应 reference
, byte
, char
, short
, int
, long
, float
, double
类型)。getfield
(Fetch field from object): 获取对象的实例字段的值,对象引用从操作数栈弹出,字段值推送到栈顶。putfield
(Set field in object): 设置对象的实例字段的值,对象引用和要设置的字段值从操作数栈弹出。getstatic
(Get static field from class): 获取类的静态字段的值,字段值推送到操作数栈顶。putstatic
(Set static field in class): 设置类的静态字段的值,要设置的字段值从操作数栈弹出。6. 方法调用和返回指令:
invokevirtual
(Invoke virtual method): 调用对象的虚方法 (运行时多态)。invokespecial
(Invoke instance method; special handling): 调用实例方法,但需要特殊处理的情况,例如:
super.method()
)
)invokestatic
(Invoke a class (static) method): 调用静态方法。invokeinterface
(Invoke interface method): 调用接口方法。invokedynamic
(Invoke dynamic method): 用于支持动态语言特性,例如 Lambda 表达式、动态代理等 (JDK 7 新增)。ireturn
, freturn
, areturn
, lreturn
, dreturn
(Return from method): 从方法返回,并将栈顶的 int
, float
, reference
, long
, double
类型值作为返回值返回。return
(Return void from method): 从 void
方法返回。7. 控制流指令:
ifeq
(If int compare with zero is equal branch): 如果栈顶 int
型数值等于 0,则跳转。ifne
(If int compare with zero is not equal branch): 如果栈顶 int
型数值不等于 0,则跳转。iflt
(If int compare with zero is less than branch): 如果栈顶 int
型数值小于 0,则跳转。ifge
(If int compare with zero is greater than or equal branch): 如果栈顶 int
型数值大于等于 0,则跳转。ifgt
(If int compare with zero is greater than branch): 如果栈顶 int
型数值大于 0,则跳转。ifle
(If int compare with zero is less than or equal branch): 如果栈顶 int
型数值小于等于 0,则跳转。if_icmpeq
(If int compare equal branch): 如果栈顶两个 int
型数值相等,则跳转。if_icmpne
(If int compare not equal branch): 如果栈顶两个 int
型数值不相等,则跳转。if_icmplt
(If int compare less than branch): 如果栈顶第一个 int
型数值小于第二个,则跳转。if_icmpge
(If int compare greater than or equal branch): 如果栈顶第一个 int
型数值大于等于第二个,则跳转。if_icmpgt
(If int compare greater than branch): 如果栈顶第一个 int
型数值大于第二个,则跳转。if_icmple
(If int compare less than or equal branch): 如果栈顶第一个 int
型数值小于等于第二个,则跳转。ifnull
(If reference is null branch): 如果栈顶 reference
型数值为 null
,则跳转。ifnonnull
(If reference is not null branch): 如果栈顶 reference
型数值不为 null
,则跳转。goto
(Branch always): 无条件跳转到指定偏移量。goto_w
(Branch always wide): 宽偏移量版本 goto
,用于跳转范围更大的情况。tableswitch
(Access jump table by index and jump): 用于 switch
语句 (当 case
值连续时)。lookupswitch
(Access jump table by key match and jump): 用于 switch
语句 (当 case
值不连续时)。8. 异常处理指令:
athrow
(Throw exception or error): 将栈顶的异常对象抛出。checkcast
(Check whether object is of given type): 检查对象类型,如果类型不匹配,抛出 ClassCastException
(也可以用于类型检查,不仅仅是异常处理)。monitorenter
(Enter monitor for object): 尝试获取对象的 monitor (锁),用于 synchronized
关键字的同步块的开始。monitorexit
(Exit monitor for object): 释放对象的 monitor (锁),用于 synchronized
关键字的同步块的结束。类型缩写:
在指令助记符中,通常会使用一些类型缩写来表示操作的数据类型:
i
: intl
: longf
: floatd
: doublea
: reference (对象引用)b
: bytec
: chars
: short学习建议:
javap -c <类名>
命令反编译 .class
文件查看字节码。