jvm指令集

1、Java中查看class文件指令
javap -c xxxx.class #对代码文件进行反汇编

2、jvm指令集

助记符 操作码 描述
nop 0x00 不执行任何操作
aconst_null 0x01 将null存入栈中
iconst_m1 0x02 将int型-1存入栈中
iconst_0 0x03 将int型0存入栈中
iconst_1 0x04 将int型1存入栈中
iconst_2 0x05 将int型2存入栈中
iconst_3 0x06 将int型3存入栈中
iconst_4 0x07 将int型4存入栈中
iconst_5 0x08 将int型5存入栈中
lconst_0 0x09 将long型0存入栈中
lconst_1 0x0a 将long型1存入栈中
fconst_0 0x0b 将float型0存入栈中
fconst_1 0x0c 将float型1存入栈中
fconst_2 0x0d 将float型2存入栈中
dconst_0 0x0e 将double型0.0存入栈中
dconst_1 0x0f 将double型1.0存入栈中
bipush 0x10 将指定byte值(-27~27-1)作为int型值存入栈中
sipush 0x11 将指定short值(-215~215-1)作为int型值存入栈中
ldc 0x12 从常量池(String, int, float, Class, MethodType, MethodHandle)加载指定值到栈中
ldc_w 0x13 从常量池(String, int, float, Class, MethodType, MethodHandle)加载指定值到栈中(索引宽度构造为indexbyte1 << 8 + indexbyte2)
ldc2_w 0x14 从常量池(double,long)加载指定值到栈中(索引宽度构造为indexbyte1 << 8 + indexbyte2)
iload 0x15 将本地指定的int型值存入栈中
lload 0x16 将本地指定的long型值存入栈中
fload 0x17 将本地指定的float型值存入栈中
dload 0x18 将本地指定的double型值存入栈中
aload 0x19 将本地指定的引用存入栈中
iload_0 0x1a 将第0个本地int值存入栈中
iload_1 0x1b 将第1个本地int值存入栈中
iload_2 0x1c 将第2个本地int值存入栈中
iload_3 0x1d 将第3个本地int值存入栈中
lload_0 0x1e 将第0个本地long 值存入栈中
lload_1 0x1f 将第1个本地long 值存入栈中
lload_2 0x20 将第2个本地long 值存入栈中
lload_3 0x21 将第3个本地long 值存入栈中
fload_0 0x22 将第0个本地float 值存入栈中
fload_1 0x23 将第1个本地float 值存入栈中
fload_2 0x24 将第2个本地float 值存入栈中
fload_3 0x25 将第3个本地float 值存入栈中
dload_0 0x26 将第0个本地double值存入栈中
dload_1 0x27 将第1个本地double值存入栈中
dload_2 0x28 将第2个本地double值存入栈中
dload_3 0x29 将第3个本地double值存入栈中
aload_0 0x2a 将第0个本地引用存入栈中
aload_1 0x2b 将第1个本地引用存入栈中
aload_2 0x2c 将第2个本地引用存入栈中
aload_3 0x2d 将第3个本地引用存入栈中
iaload 0x2e 将int型数组指定索引的值存入栈中
laload 0x2f 将long型数组指定索引的值存入栈中
faload 0x30 将float型数组指定索引的值存入栈中
daload 0x31 将double型数组指定索引的值存入栈中
aaload 0x32 将引用型数组指定索引的值存入栈中
baload 0x33 将byte/Boolean型数组指定索引的值存入栈中
caload 0x34 将char型数组指定索引的值存入栈中
saload 0x35 将short型数组指定索引的值存入栈中
istore 0x36 将栈顶int值存入指定变量
lstore 0x37 将栈顶long值存入指定本地变量
fstore 0x38 将栈顶float值存入指定本地变量
dstore 0x39 将栈顶double值存入指定本地变量
astore 0x3a 将栈顶引用型值存入指定本地变量
istore_0 0x3b 将栈顶int值存入第0个本地变量
istore_1 0x3c 将栈顶int值存入第1个本地变量
istore_2 0x3d 将栈顶int值存入第2个本地变量
istore_3 0x3e 将栈顶int值存入第3个本地变量
lstore_0 0x3f 将栈顶long值存入第0个本地变量
lstore_1 0x40 将栈顶long值存入第1个本地变量
lstore_2 0x41 将栈顶long值存入第2个本地变量
lstore_3 0x42 将栈顶long值存入第3个本地变量
fstore_0 0x43 将栈顶float值存入第0个本地变量
fstore_1 0x44 将栈顶float值存入第1个本地变量
fstore_2 0x45 将栈顶float值存入第2个本地变量
fstore_3 0x46 将栈顶float值存入第3个本地变量
dstore_0 0x47 将栈顶double值存入第0个本地变量
dstore_1 0x48 将栈顶double值存入第1个本地变量
dstore_2 0x49 将栈顶double值存入第2个本地变量
dstore_3 0x4a 将栈顶double值存入第3个本地变量
astore_0 0x4b 将栈顶引用值存入第0个本地变量
astore_1 0x4c 将栈顶引用值存入第1个本地变量
astore_2 0x4d 将栈顶引用值存入第2个本地变量
astore_3 0x4e 将栈顶引用值存入第3个本地变量
iastore 0x4f 将栈顶int值存入指定数组指定索引位置
lastore 0x50 将栈顶long值存入指定数组指定索引位置
fastore 0x51 将栈顶float值存入指定数组指定索引位置
dastore 0x52 将栈顶double值存入指定数组指定索引位置
aastore 0x53 将栈顶引用型值存入指定数组指定索引位置
bastore 0x54 将栈顶byte/boolean值存入指定数组指定索引位置
castore 0x55 将栈顶char值存入指定数组指定索引位置
sastore 0x56 将栈顶short值存入指定数组指定索引位置
pop 0x57 弹出栈顶的值
pop2 0x58 丢弃栈顶的前两个值(如果是double或long则弹出一个)
dup 0x59 复制栈顶的值并存入栈顶
dup_x1 0x5a 复制栈顶的两个值并存入栈中(栈顶的两个值不能为double/long)
dup_x2 0x5b 复制栈顶的两个(第二个值为double/long)或者三个(第二个值不是double/long)值并存入栈中
dup2 0x5c 复制栈顶的两个单词到栈中(非double/long为两个单词,double/long为一个单词)
dup2_x1 0x5d 复制栈顶的两个单词并插入到第三个词下面(非double/long为两个单词,double/long为一个单词)
dup2_x2 0x5e 复制两个单词并插入到第四个单词下(非double/long为两个单词,double/long为一个单词)
swap 0x5f 交换栈顶的两个值(两个值不能为long/double)
iadd 0x60 对栈顶两个int相加后存入栈中
ladd 0x61 对栈顶两个long相加后存入栈中
fadd 0x62 对栈顶两个float相加后存入栈中
dadd 0x63 对栈顶两个double相加后存入栈中
isub 0x64 对栈顶两个int相减后存入栈中
lsub 0x65 对栈顶两个long相减后存入栈中
fsub 0x66 对栈顶两个float相减后存入栈中
dsub 0x67 对栈顶两个double相减后存入栈中
imul 0x68 对栈顶两个int相乘后存入栈中
lmul 0x69 对栈顶两个long相乘后存入栈中
fmul 0x6a 对栈顶两个float相乘后存入栈中
dmul 0x6b 对栈顶两个double相乘后存入栈中
idiv 0x6c 对栈顶两个int相除后存入栈中
ldiv 0x6d 对栈顶两个long相除后存入栈中
fdiv 0x6e 对栈顶两个float相除后存入栈中
ddiv 0x6f 对栈顶两个double相除后存入栈中
irem 0x70 对栈顶两int取余后存入栈中
lrem 0x71 对栈顶两long取余后存入栈中
frem 0x72 对栈顶两float取余后存入栈中
drem 0x73 将栈顶两double取余的结果存入栈中
ineg 0x74 将栈顶的int的负值存入栈中
lneg 0x75 将栈顶的long的负值存入栈中
fneg 0x76 将栈顶的float的负值存入栈中
dneg 0x77 将栈顶的double的负值存入栈中
ishl 0x78 将int值左移value2位
lshl 0x79 将long(value1)左移int(value2)位
ishr 0x7a 将int带符号右移value2位
lshr 0x7b 将long(value1)带符号右移int(value2)位
iushr 0x7c 将int(value1)无符号右移int(value2)位
lushr 0x7d 将long(value1)无符号右移int(value2)位
iand 0x7e 两个int按位与
land 0x7f 两个long按位与
ior 0x80 两个int按位或
lor 0x81 两个long按位或
ixor 0x82 两个int按位异或
lxor 0x83 两个long按位异或
iinc 0x84 将第index个int增加const
i2l 0x85 将int转换为long
i2f 0x86 将int转换为float
i2d 0x87 将int转换为double
l2i 0x88 将long转换为int
l2f 0x89 将long转换为float
l2d 0x8a 将long转换为double
f2i 0x8b 将float转换为int
f2l 0x8c 将float转换为long
f2d 0x8d 将float转换为double
d2i 0x8e 将double转换为int
d2l 0x8f 将double转换为long
d2f 0x90 将double转换为float
i2b 0x91 将int转换为byte
i2c 0x92 将int转换为char
i2s 0x93 将int转换为short
lcmp 0x94 比较两个long值(value1=value2为0;value1>value2为1;value1<value2为-1)
fcmpl 0x95 比较两个float值(value1=value2为0;value1>value2为1;value1<value2为-1);当其中一个为NaN时为-1
fcmpg 0x96 比较两个float值(value1=value2为0;value1>value2为1;value1<value2为-1);当其中一个为NaN时为1
dcmpl 0x97 比较两个double值(value1=value2为0;value1>value2为1;value1<value2为-1);当其中一个为NaN时为-1
dcmpg 0x98 比较两个float值(value1=value2为0;value1>value2为1;value1<value2为-1);当其中一个为NaN时为1
ifeq 0x99 如果栈顶值为0跳转
ifne 0x9a 如果栈顶值!=0跳转
iflt 0x9b 如果栈顶值<0跳转
ifge 0x9c 如果栈顶值>=0跳转
ifgt 0x9d 如果栈顶值>0跳转
ifle 0x9e 如果栈顶值<=0跳转
if_icmpeq 0x9f 如果两个int值相等跳转
if_icmpne 0xa0 如果两个int值不相等跳转
if_icmplt 0xa1 如果value1<value2跳转(两个值均为int)
if_icmpge 0xa2 如果value1>=value2跳转(两个值均为int)
if_icmpgt 0xa3 如果value1>value2跳转(两个值均为int)
if_icmple 0xa4 当value1<=value2是跳转(两个值均为int)
if_acmpeq 0xa5 如果两个引用值相等跳转
if_acmpne 0xa6 如果两个引用值不相等跳转
goto 0xa7 无条件跳转
jsr 0xa8 跳转至指定位置的子程序,并将jsr下一条指令地址存入栈顶
ret 0xa9 返回至本地变量指定的index的指令位置(一般与jsr, jsr_w联合使用)
tableswitch 0xaa 用于switch条件跳转,case值连续(可变长度指令)
lookupswitch 0xab 用于switch条件跳转,case值不连续(可变长度指令)
ireturn 0xac 从当前方法返回int
lreturn 0xad 从当前方法返回long
freturn 0xae 从当前方法返回float
dreturn 0xaf 从当前方法返回double
areturn 0xb0 从当前方法返回一个引用型值
return 0xb1 从当前方法返回
getstatic 0xb2 获取类的静态字段,字段由常量池索引中的字段引用标识(indexbyte1 << 8 + indexbyte2)
putstatic 0xb3 将静态字段设置为类中的值,字段由常量池索引中的字段引用标识(indexbyte1 << 8 + indexbyte2)
getfield 0xb4 获取实例指定字段值
putfield 0xb5 为实例指定字段赋值
invokevirtual 0xb6 调用实例虚方法,并将结果存入栈中
invokespecial 0xb7 调用实例方法,并将结果存入栈中
invokestatic 0xb8 调用静态方法,并将结果存入栈中
invokeinterface 0xb9 调用接口方法,并将结果存入栈中
invokedynamic 0xba 调用动态方法,并将结果存入栈中
new 0xbb 创建一个类常量池中index为指定值的引用型值,并存入栈中
newarray 0xbc 创建count长度的指定的基本类型数组
anewarray 0xbd 创建count长度的指定引用类型数组
arraylength 0xbe 获取数组长度
athrow 0xbf 抛出异常(栈的其余部分已被清除,只留下对异常对象的引用)
checkcast 0xc0 检验类型转换,检验未通过将抛出ClassCastException
instanceof 0xc1 检验对象是否是指定的类的实例
monitorenter 0xc2 获取对像监视控器(synchronized()的开始部分)
monitorexit 0xc3 退出对象监视器(synchronized()的结束部分)
wide 0xc4 执行操作码,其中操作码为iload、fload、aload、lload、dload、istore、fstore、astore、lstore、dstore或ret(但假设索引为16位);或者执行iinc,其中索引是16位,要增加的常量是一个带符号的16位short

multianewarray 0xc5 创建一个指定长度指定泛型的数组
ifnull 0xc6 value为null时执行指令
ifnonnull 0xc7 value不为null时执行指令
goto_w 0xc8 跳转到指定指令
jsr_w 0xc9 跳转到子程序
breakpoint 0xca 预留给Java调试器中的断点;不应该出现在任何类文件中吗
(no name) 0xcb-0xfd 这些值目前未分配给操作码,保留给将来使用
impdep1 0xfe 保留给调试器中与实现相关的操作;不应该出现在任何类文件中
impdep2 0xff 保留给调试器中与实现相关的操作;不应该出现在任何类文件中

3、实战
Test.java文件
package com.bin;
public class Test {
public int add(){
int a =1;
int b =2;
int c = a+b;
return c;
}
public static void main(String[] args) {
Test test = new Test();
test.add();
}
}

对Test.class代码文件进行反汇编后的Test.txt文件
javap -c Test.class > Test.txt

Compiled from “Test.java”
public class com.bin.Test {
public com.bin.Test();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object.""????)V
4: return

public int add();
Code:
0: iconst_1 //将int型1存入栈中 1
1: istore_1 //将栈顶int值存入第1个本地变量 a=1
2: iconst_2 //将int型2存入栈中 2
3: istore_2 //将栈顶int值存入第2个本地变量 b=2
4: iload_1 //将第1个本地int值存入栈中 1
5: iload_2 //将第2个本地int值存入栈中 2
6: iadd //对栈顶两个int相加后存入栈中 1+2=3
7: istore_3 //将栈顶int值存入第3个本地变量 c=3
8: iload_3 //将第3个本地int值存入栈中 c=3
9: ireturn //从当前方法返回int

public static void main(java.lang.String[]);
Code:
0: new #1 // class com/bin/Test
//创建一个类常量池中index为指定值的引用型值,并存入栈中 test
3: dup //复制栈顶的值并存入栈顶
4: invokespecial #22 // Method “”????)V
//调用实例方法,并将结果存入栈中 add
7: astore_1 //将栈顶引用值存入第1个本地变量
8: aload_1 //将第1个本地引用存入栈中
9: invokevirtual #23 // Method add:()I
//调用实例虚方法,并将结果存入栈中
12: pop //弹出栈顶的值
13: return //从当前方法返回int
}

4、画图展示
jvm指令集