深入理解JVM虚拟机字节码指令集
在Java虚拟机的指令集中,大多数指令都包含其操作所对应的数据类型信息,如:i代表对int类型的数据操作,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference。
解释器的执行模型
Java虚拟机的解释器的执行模型:
do { 自动计算PC寄存器的值加1;
根据PC寄存器指示的位置,从字节码流中取出操作码;
if (字节码存在操作数) 从字节码流中取出操作数;
执行操作码所定义的操作;
} while (字节码流长度 > 0);
常量入栈指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0x01
aconst_null
将 null推送至栈顶
0x02
iconst_m1
将 -1(int)推送至栈顶
0x03
iconst_0
将 0(int)推送至栈顶
0x04
iconst_1
将 1(int)推送至栈顶
0x05
iconst_2
将 2(int)推送至栈顶
0x06
iconst_3
将 3(int)推送至栈顶
0x07
iconst_4
将 4(int)推送至栈顶
0x08
iconst_5
将 5(int)推送至栈顶
0x09
lconst_0
将 0(long)推送至栈顶
0x0a
lconst_1
将 1(long)推送至栈顶
0x0b
fconst_0
将 0(float)推送至栈顶
0x0c
fconst_1
将 1(float)推送至栈顶
0x0d
fconst_2
将 2(float)推送至栈顶
0x0e
dconst_0
将 0(double)推送至栈顶
0x0f
dconst_1
将 1(double)推送至栈顶
0x10
bipush
valuebyte
将一个byte值带符号扩展成int推送至栈顶
0x11
sipush
valuebyte1<br/>valuebyte2
将一个short值带符号扩展成int推送至栈顶
0x12
ldc
indexbyte1
将int、float或String型常量值从常量池中推送至栈顶
0x13
ldc_w
indexbyte1<br/>indexbyte2
将int、float或String型常量值从常量池中推送至栈顶(宽索引)
0x14
ldc2_w
indexbyte1<br/>indexbyte2
将long或double型常量值从常量池中推送至栈顶(宽索引)
局部变量值转载到栈中指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0x15
iload
indexbyte
从局部变量indexbyte中装载int类型值推送至栈顶
0x16
lload
indexbyte
从局部变量indexbyte中装载long类型值推送至栈顶
0x17
fload
indexbyte
从局部变量indexbyte中装载float类型值推送至栈顶
0x18
dload
indexbyte
从局部变量indexbyte中装载double类型值推送至栈顶
0x19
aload
indexbyte
从局部变量indexbyte中装载引用类型值推送至栈顶
0x1a
iload_0
将第1个int型本地变量推送至栈顶
0x1b
iload_1
将第2个int型本地变量推送至栈顶
0x1c
iload_2
将第4个int型本地变量推送至栈顶
0x1d
iload_3
将第4个int型本地变量推送至栈顶
0x1e
lload_0
将第1个long型本地变量推送至栈顶
0x1f
lload_1
将第2个long型本地变量推送至栈顶
0x20
lload_2
将第3个long型本地变量推送至栈顶
0x21
lload_3
将第4个long型本地变量推送至栈顶
0x22
fload_0
将第1个float型本地变量推送至栈顶
0x23
fload_1
将第2个float型本地变量推送至栈顶
0x24
fload_2
将第3个float型本地变量推送至栈顶
0x25
fload_3
将第4个float型本地变量推送至栈顶
0x26
dload_0
将第1个double型本地变量推送至栈顶
0x27
dload_1
将第2个double型本地变量推送至栈顶
0x28
dload_2
将第3个double型本地变量推送至栈顶
0x29
dload_3
将第4个double型本地变量推送至栈顶
0x2a
aload_0
将第1个引用类型本地变量推送至栈顶
0x2b
aload_1
将第2个引用类型本地变量推送至栈顶
0x2c
aload_2
将第3个引用类型本地变量推送至栈顶
0x2d
aload_3
将第4个引用类型本地变量推送至栈顶
0x2e
iaload
将int类型数组的索引值推送至栈顶
0x2f
laload
将long类型数组的索引值推送至栈顶
0x30
faload
将float类型数组的索引值推送至栈顶
0x31
daload
将double类型数组的索引值推送至栈顶
0x32
aaload
将引用类型数组的索引值推送至栈顶
0x33
baload
将boolean或byte类型数组的索引值推送至栈顶(先转换为int类型值,后压栈)
0x34
caload
将char类型数组的索引值推送至栈顶(先转换为int类型值,后压栈)
0x35
saload
将short类型数组的索引值推送至栈顶(先转换为int类型值,后压栈)
将栈顶值保存到局部变量中指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0x36
(wide)istore
indexbyte
将栈顶int类型值保存到局部变量indexbyte中
0x37
(wide)lstore
indexbyte
将栈顶long类型值保存到局部变量indexbyte中
0x38
(wide)fstore
indexbyte
将栈顶float类型值保存到局部变量indexbyte中
0x39
(wide)dstore
indexbyte
将栈顶double类型值保存到局部变量indexbyte中
0x3a
(wide)astore
indexbyte
将栈顶引用类型值保存到局部变量indexbyte中
0x3b
istore_0
将栈顶int类型值保存到局部变量0中
0x3c
istore_1
将栈顶int类型值保存到局部变量1中
0x3d
istore_2
将栈顶int类型值保存到局部变量2中
0x3e
istore_3
将栈顶int类型值保存到局部变量3中
0x3f
lstore_0
将栈顶long类型值保存到局部变量0中
0x40
lstore_1
将栈顶long类型值保存到局部变量1中
0x41
lstore_2
将栈顶long类型值保存到局部变量2中
0x42
lstroe_3
将栈顶long类型值保存到局部变量3中
0x43
fstore_0
将栈顶float类型值保存到局部变量0中
0x44
fstore_1
将栈顶float类型值保存到局部变量1中
0x45
fstore_2
将栈顶float类型值保存到局部变量2中
0x46
fstore_3
将栈顶float类型值保存到局部变量3中
0x47
dstore_0
将栈顶double类型值保存到局部变量0中
0x48
dstore_1
将栈顶double类型值保存到局部变量1中
0x49
dstore_2
将栈顶double类型值保存到局部变量2中
0x4a
dstore_3
将栈顶double类型值保存到局部变量3中
0x4b
astroe_0
将栈顶引用类型值保存到局部变量0中
0x4c
astore_1
将栈顶引用类型值保存到局部变量1中
0x4d
astore_2
将栈顶引用类型值保存到局部变量2中
0x4e
astore_3
将栈顶引用类型值保存到局部变量3中
0x4f
iastore
将栈顶int类型值保存到指定int类型数组的指定索引位
0x50
lastore
将栈顶long类型值保存到指定long类型数组的指定索引位
0x51
fastore
将栈顶float类型值保存到指定float类型数组的指定索引位
0x52
dastore
将栈顶double类型值保存到指定double类型数组的指定索引位
0x53
aastore
将栈顶引用类型值保存到指定引用类型数组的指定索引位
0x54
bastroe
将栈顶boolean类型值或byte类型值保存到指定boolean类型数组或byte类型数组的指定索引位
0x55
castore
将栈顶char类型值保存到指定char类型数组的指定索引位
0x56
sastore
将栈顶short类型值保存到指定short类型数组的指定索引位
通用(无类型)栈操作指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0x00
nop
空操作
0x57
pop
从栈顶弹出一个字长的数据(不是long和double)
0x58
pop2
从栈顶弹出两个字长的数据(一个long或double,或者是两个单字节长度数值)
0x59
dup
复制栈顶一个字长的数据,将复制后的数据压入栈顶
0x5a
dup_x1
复制栈顶一个字长的数据,弹出栈顶两个字长数据,先将复制后的数据压入栈顶,再将弹出的两个字长数据压入栈顶
0x5b
dup_x2
复制栈顶一个字长的数据,弹出栈顶三个字长的数据,将复制后的数据压入栈顶,再将弹出的三个字长的数据压入栈顶
0x5c
dup2
复制栈顶两个字长的数据,将复制后的两个字长的数据压入栈顶
0x5d
dup2_x1
dup_x1 指令的双倍版
0x5e
dup2_x2
dup_x2 指令的双倍版
0x5f
swap
将栈最顶端的两个数值互换(数值不能是long或double)
整数和浮动点数运算
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0x60
iadd
将栈顶两int类型数相加,并将结果压入栈顶
0x61
ladd
将栈顶两long类型数相加,并将结果压入栈顶
0x62
fadd
将栈顶两float类型数相加,并将结果压入栈顶
0x63
dadd
将栈顶两double类型数相加,并将结果压入栈顶
0x64
isub
将栈顶两int类型数相减,并将结果压入栈顶
0x65
lsub
将栈顶两long类型数相减,并将结果压入栈顶
0x66
fsub
将栈顶两float类型数相减,并将结果压入栈顶
0x67
dsub
将栈顶两double类型数相减,并将结果压入栈顶
0x68
imul
将栈顶两int类型数相乘,并将结果压入栈顶
0x69
lmul
将栈顶两long类型数相乘,并将结果压入栈顶
0x6a
fmul
将栈顶两float类型数相乘,并将结果压入栈顶
0x6b
dmul
将栈顶两double类型数相乘,并将结果压入栈顶
0x6c
idiv
将栈顶两int类型数相除,并将结果压入栈顶
0x6d
ldiv
将栈顶两long类型数相除,并将结果压入栈顶
0x6e
fdiv
将栈顶两float类型数相除,并将结果压入栈顶
0x6f
ddiv
将栈顶两double类型数相除,并将结果压入栈顶
0x70
irem
将栈顶两int类型数取模,并将结果压入栈顶
0x71
lrem
将栈顶两long类型数取模,并将结果压入栈顶
0x72
frem
将栈顶两float类型数取模,并将结果压入栈顶
0x73
drem
将栈顶两double类型数取模,并将结果压入栈顶
0x74
ineg
将栈顶int类型值取负,并将结果压入栈顶
0x75
lneg
将栈顶long类型值取负,并将结果压入栈顶
0x76
fneg
将栈顶float类型值取反,并将结果压入栈顶
0x77
dneg
将栈顶double类型值取负,并将结果压入栈顶
0x84
(wide)iinc
indexbyte<br/>constbyte
将整数值constbyte加到indexbyte指定的int类型的局部变量中(i++,i--,i+=2;)
逻辑运算 - 移位运算
指令码 操作码(助记符) 操作数栈 描述(栈指操作数栈)
0x78
ishl
... , a , n
(a << n) 左移int类型值,并将结果压入栈顶
0x79
lshl
... , a , n
(a << n) 左移long类型值,并将结果压入栈顶
0x7a
ishr
... , a , n
(a >> n) 算术右移int类型值,并将结果压入栈顶
0x7b
lshr
... , a , n
(a >> n) 算术右移long类型值,并将结果压入栈顶
0x7c
iushr
... , a , n
(a >>> n) 逻辑右移int类型值,并将结果压入栈顶
0x7d
lushr
... , a , n
(a >>> n) 逻辑右移long类型值,并将结果压入栈顶
逻辑运算 - 位运算
指令码 操作码(助记符) 操作数栈 描述(栈指操作数栈)
0x7e
iand
... , a , n
(a & b) 对int类型按位与运算,并将结果压入栈顶
0x7f
land
... , a , n
(a & b) 对long类型的按位与运算,并将结果压入栈顶
0x80
ior
... , a , n
(a | b) 对int类型的按位或运算,并将结果压入栈顶
0x81
lor
... , a , n
(a | b) 对long类型的按位或运算,并将结果压入栈顶
0x82
ixor
... , a , n
(a ^ b) 对int类型的按位异或运算,并将结果压入栈顶
0x83
lxor
... , a , n
(a ^ b) 对long类型的按位异或运算,并将结果压入栈顶
类型转换指令
指令码 操作码(助记符) 操作数栈 描述(栈指操作数栈)
0x85
i2l
... , a
(long) a, 将栈顶int类型值转换为long类型值,并将结果压入栈顶
0x86
i2f
... , a
(float) a, 将栈顶int类型值转换为float类型值,并将结果压入栈顶
0x87
i2d
... , a
(double) a, 将栈顶int类型值转换为double类型值,并将结果压入栈顶
0x88
l2i
... , a
(int) a, 将栈顶long类型值转换为int类型值,并将结果压入栈顶
0x89
l2f
... , a
(float) a, 将栈顶long类型值转换为float类型值,并将结果压入栈顶
0x8a
l2d
... , a
(double) a, 将栈顶long类型值转换double类型值,并将结果压入栈顶
0x8b
f2i
... , a
(int) a, 将栈顶float类型值转换为int类型值,并将结果压入栈顶
0x8c
f2l
... , a
(long) a, 将栈顶float类型值转换为long类型值,并将结果压入栈顶
0x8d
f2d
... , a
(double) a, 将栈顶float类型值转换为double类型值,并将结果压入栈顶
0x8e
d2i
... , i
(double) a, 将栈顶double类型值转换为int类型值,并将结果压入栈顶
0x8f
d2l
... , a
(long) a, 将栈顶double类型值转换为long类型值,并将结果压入栈顶
0x90
d2f
... , a
(float) a, 将栈顶double类型值转换为float类型值,并将结果压入栈顶
0x91
i2b
... , a
(byte) a, 将栈顶int类型值截断成byte类型,后带符号扩展成int类型值压入栈顶
0x92
i2c
... , a
(char) a, 将栈顶int类型值截断成char类型值,后带符号扩展成int类型值压入栈顶
0x93
i2s
... , a
(short) a, 将栈顶int类型值截断成short类型值,后带符号扩展成int类型值压入栈顶
控制流指令 - 比较指令
指令码 操作码(助记符) 操作数栈 描述(栈指操作数栈)
0x94
lcmp
... , a , b
比较栈顶两long类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈 [a == b ? 0 : (a < b ? -1 : 1)]
0x95
fcmpl
... , a , b
比较栈顶两float类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈;有NaN存在,-1入栈 [a == b ? 0 : (a < b ? -1 : 1)]
0x96
fcmpg
... , a , b
比较栈顶两float类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈;有NaN存在,-1入栈 [a == b ? 0 : (a < b ? -1 : 1)]
0x97
dcmpl
... , a , b
比较栈顶两double类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈;有NaN存在,-1入栈 [a == b ? 0 : (a < b ? -1 : 1)]
0x98
dcmpg
... , a , b
比较栈顶两double类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈;有NaN存在,-1入栈 [a == b ? 0 : (a < b ? -1 : 1)]
控制流指令 - 条件跳转指令
指令码 操作码(助记符) 栈操作之前 栈操作之后 描述(栈指操作数栈)
0x99
ifeq
... , i
...
若栈顶int类型值为0则跳转 (jump if i == 0)
0x9a
ifne
... , i
...
若栈顶int类型值不为0则跳转 (jump if i != 0)
0x9b
iflt
... , i
...
若栈顶int类型值小于0则跳转 (jump if i < 0)
0x9c
ifge
... , i
...
若栈顶int类型值大于等于0则跳转 (jump if i >= 0)
0x9d
ifgt
... , i
...
若栈顶int类型值大于0则跳转 (jump if i > 0)
0x9e
ifle
... , i
...
若栈顶int类型值小于等于0则跳转 (jump if i <= 0)
0x9f
if_icmpeq
... , i , j
...
若栈顶两int类型值相等则跳转 (jump if i == j)
0xa0
if_icmpne
... , i , j
...
若栈顶两int类型值不相等则跳转 (jump if i != j)
0xa1
if_icmplt
... , i , j
...
若栈顶两int类型值前小于后则跳转 (jump if i < j)
0xa4
if_icmple
... , i , j
...
若栈顶两int类型值前小于等于后则跳转 (jump if i <= j)
0xa3
if_icmpgt
... , i , j
...
若栈顶两int类型值前大于后则跳转 (jump if i > j)
0xa2
if_icmpge
... , i , j
...
若栈顶两int类型值前大于等于后则跳转 (jump if i >= j)
0xa5
if_acmpeq
... , o , p
...
若栈顶两引用类型值相等则跳转 (jump if o == p)
0xa6
if_acmpne
... , o , p
...
若栈顶两引用类型值不相等则跳转 (jump if o != p)
0xc6
ifnull
... , o
...
若栈顶引用值为null则跳转 (jump if o == null)
0xc7
ifnonnull
... , o
...
若栈顶引用值不为null则跳转 (jump if o != null)
控制流指令 - 无条件跳转指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0xa7
goto
branchbyte1<br/>branchbyte2
无条件跳转到指定位置
0xc8
goto_w
branchbyte1<br/>branchbyte2<br/>branchbyte3<br/>branchbyte4
无条件跳转到指定位置(宽索引)
控制流指令 - 表跳转指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0xaa
tableswitch
<0 - 3bytepad><br/>defaultbyte1<br/>defaultbyte2<br/>defaultbyte3<br/>defaultbyte4<br/>lowbyte1<br/>lowbyte2<br/>lowbyte3<br/>lowbyte4<br/>highbyte1<br/>highbyte2<br/>highbyte3<br/>highbyte4<br/>jump offsets...
通过索引访问跳转表,并跳转<br/> jump always
0xab
lookupswitch
<0 - 3bytepad><br/>defaultbyte1<br/>defaultbyte2<br/>defaultbyte3<br/>defaultbyte4<br/>npairs1<br/>npairs2<br/>npairs3<br/>npairs4<br/>match offsets
通过键值访问跳转表,并跳转<br/> jump always
控制流指令 - 异常和finally
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0xbf
athrow
抛出异常
0xa8
jsr
branchbyte1<br/>branchbyte2
跳转到子例程序
0xc9
jsr_w
branchbyte1<br/>branchbyte2<br/>branchbyte3<br/>branchbyte4
跳转到子例程序(宽索引)
0xa9
(wide)ret
indexbyte
返回子例程序
对象操作指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0xbb
new
indexbyte1<br/>indexbyte2
创建新的对象实例,并将其引用压入栈顶
0xc0
checkcast
indexbyte1<br/>indexbyte
类型强转,如果该检查未通过将会抛出ClassCastException异常
0xc1
instanceof
indexbyte1<br/>indexbyte2
检查对象是否是指定的类的实例。如果是,1进栈;否则,0进栈
0xb2
getstatic
indexbyte1<br/>indexbyte2
获取静态字段的值,并将其引用压入栈顶
0xb3
putstatic
indexbyte1<br/>indexbyte2
给静态字段赋值
0xb4
getfield
indexbyte1<br/>indexbyte2
获取对象字段的值,并将其引用压入栈顶
0xb5
putfield
indexbyte1<br/>indexbyte2
给对象字段赋值
数组操作指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0xbc
newarray
atype
创建type类型的数组
0xbd
anewarray
indexbyte1<br/>indexbyte2
创建引用类型的数组
0xbe
arraylength
获取一维数组的长度
0xc5
multianewarray
indexbyte1<br/>indexbyte2<br/>dimension
创建dimension维度的数组
方法调用指令
指令码 操作码(助记符) 操作数 描述(栈指操作数栈)
0xb7
invokespecial
indexbyte1<br/>indexbyte2
编译时方法绑定调用方法
0xb6
invokevirtual
indexbyte1<br/>indexbyte2
运行时方法绑定调用方法
0xb8
invokestatic
indexbyte1<br/>indexbyte2
调用静态方法
0xb9
invokeinterface
indexbyte1<br/>indexbyte2<br/>count<br/>0
调用接口方法
方法返回指令
指令码 操作码(助记符) 描述(栈指操作数栈)
0xac
ireturn
返回int类型值
0xad
lreturn
返回long类型值
0xae
freturn
返回float类型值
0xaf
dreturn
返回double类型值
0xb0
areturn
返回引用类型值
0xb1
return
void函数返回
线程同步指令
指令码 操作码(助记符) 描述(栈指操作数栈)
0xc2
monitorenter
进入并获得对象监视器,获取对象锁,用于同步方法或者同步块
0xc3
monitorexit
释放并退出对象监视器,释放对象锁,用于同步方法或者同步块
wide指令
指令码 操作码(助记符) 描述(栈指操作数栈)
0xc4
wide
使用附加字节扩展局部变量的宽度(iinc指令特殊)
示例
代码:
void onlyMe(Foo f) { synchronized(f) {
doSomething();
}
}
编译后的指令:
Method void onlyMe(Foo)0 aload_1 // 将对象f入栈
1 dup // 复制栈顶元素(即f的引用)
2 astore_2 // 将栈顶元素存储到局部变量表变量槽 2中
3 monitorenter // 以栈定元素(即f)作为锁,开始同步
4 aload_0 // 将局部变量槽 0(即this指针)的元素入栈
5 invokevirtual #5 // 调用doSomething()方法
8 aload_2 // 将局部变量Slow 2的元素(即f)入栈
9 monitorexit // 退出同步
10 goto 18 // 方法正常结束,跳转到18返回
13 astore_3 // 从这步开始是异常路径,见下面异常表的Taget 13
14 aload_2 // 将局部变量Slow 2的元素(即f)入栈
15 monitorexit // 退出同步
16 aload_3 // 将局部变量Slow 3的元素(即异常对象)入栈
17 athrow // 把异常对象重新抛出给onlyMe()方法的调用者
18 return // 方法正常返回
Exception table:
FromTo Target Type
4 10 13 any
13 16 13 any
参考
《深入理解JAVA虚拟机》
https://www.cnblogs.com/honger/p/6815198.html
以上是 深入理解JVM虚拟机字节码指令集 的全部内容, 来源链接: utcz.com/z/512838.html