JVM 指令

在 JVM 规范中定义了将近 200+ 个指令,如下表所示:

op语法描述
0x00nop无变化不执行任何操作
0x01aconst_null... → ...,nullnull 引用压入栈[^1]顶
0x02iconst_m1... → ...,-1int 常量值 -1 压入栈顶
0x03iconst_0.. . → ...,0int 常量值 0 压入栈顶
0x04iconst_1... → ...,1int 常量值 1 压入栈顶
0x05iconst_2... → ...,2int 常量值 2 压入栈顶
0x06iconst_3... → ...,3int 常量值 3 压入栈顶
0x07iconst_4... → ...,4int 常量值 4 压入栈顶
0x08iconst_5... → ...,5int 常量值 5 压入栈顶
0x09lconst_0... → ...,0Llong 常量值 0L 压入栈顶
0x0alconst_1... → ...,1Llong 常量值 1L 压入栈顶
0x0bfconst_0... → ...,0.0ffloat 常量值 0.0f 压入栈顶
0x0cfconst_1... → ...,1.0ffloat 常量值 1.0f 压入栈顶
0x0dfconst_2... → ...,2.0ffloat 常量值 1.0f 压入栈顶
0x0edconst_0... → ...,0.0double 常量值 0.0 压入栈顶
0x0fdconst_1... → ...,1.0double 常量值 1.0 压入栈顶
0x10bipush,AA[^2]... → ...,v将立即数[^3] AA 压入栈顶
0x11sipush,AAAA[^4]... → ...,v将立即数 AAAA 压入栈顶
0x12ldc,AA... → ...,v将常量池中索引为 AA 的常量压入栈顶
0x13ldc_w,AAAA... → ...,v将常量池中索引为 AAAA 的常量压入栈顶
0x14ldc2_w,AAAA... → ...,v将常量池中索引为 AAAAlongdouble 常量压入栈顶
0x15iload,AA... → ...,v将本地变量表中索引为 AAint 变量压入栈顶
0x16lload,AA... → ...,v将本地变量表中索引为 AAlong 变量压入栈顶
0x17fload,AA... → ...,v将本地变量表中索引为 AAfloat 变量压入栈顶
0x18dload,AA... → ...,v将本地变量表中索引为 AAdouble 变量压入栈顶
0x19aload,AA... → ...,v将本地变量表中索引为 AAaref 压入栈顶
0x1aiload_0... → ...,0将本地变量表中索引为 0int 变量压入栈顶
0x1biload_1... → ...,1将本地变量表中索引为 1int 变量压入栈顶
0x1ciload_2... → ...,2将本地变量表中索引为 2int 变量压入栈顶
0x1diload_3... → ...,3将本地变量表中索引为 3int 变量压入栈顶
0x1elload_0... → ...,0L将本地变量表中索引为 0long 变量压入栈顶
0x1flload_1... → ...,1L将本地变量表中索引为 1long 变量压入栈顶
0x20lload_2... → ...,2L将本地变量表中索引为 2long 变量压入栈顶
0x21lload_3... → ...,3L将本地变量表中索引为 3long 变量压入栈顶
0x22fload_0... → ...,0.0f将本地变量表中索引为 0float 变量压入栈顶
0x23fload_1... → ...,1.0f将本地变量表中索引为 1float 变量压入栈顶
0x24fload_2... → ...,2.0f将本地变量表中索引为 2float 变量压入栈顶
0x25fload_3... → ...,3.0f将本地变量表中索引为 3float 变量压入栈顶
0x26dload_0... → ...,0.0将本地变量表中索引为 0double 变量压入栈顶
0x27dload_1... → ...,1.0将本地变量表中索引为 1double 变量压入栈顶
0x28dload_2... → ...,2.0将本地变量表中索引为 2double 变量压入栈顶
0x29dload_3... → ...,3.0将本地变量表中索引为 3double 变量压入栈顶
0x2aaload_0... → ...,aref将本地变量表中索引为 0aref 压入栈顶
0x2baload_1... → ...,aref将本地变量表中索引为 1aref 压入栈顶
0x2caload_2... → ...,aref将本地变量表中索引为 2aref 压入栈顶
0x2daload_3... → ...,aref将本地变量表中索引为 3aref 压入栈顶
0x2eiaload*...,aaref,index → ...,v将数组 aaref 中索引为 index (int)int 值压入栈顶
0x2flaload...,aaref,index → ...,v将数组 aaref 中索引为 index (int)long 值压入栈顶
0x30faload...,aaref,index → ...,v将数组 aaref 中索引为 index (int)float 值压入栈顶
0x31daload...,aaref,index → ...,v将数组 aaref 中索引为 index (int)double 值压入栈顶
0x32aaload...,aaref,index → ...,v将数组 aaref 中索引为 index (int)reference 值压入栈顶
0x33baload...,aaref,index → ...,v将数组 aaref 中索引为 index (int)byteboolean 值压入栈顶
0x34caload...,aaref,index → ...,v将数组 aaref 中索引为 index (int)char 值压入栈顶
0x35saload...,aaref,index → ...,v将数组 aaref 中索引为 index (int)short 值压入栈顶
0x36istore,AA...,v → ...,int 值从栈顶弹出,并赋值给本地变量表中索引为 AA 的本地变量
0x37lstore,AA...,v → ...,long 值从栈顶弹出,并赋值给本地变量表中索引为 AA 的本地变量
0x38fstore,AA...,v → ...,float 值从栈顶弹出,并赋值给本地变量表中索引为 AA 的本地变量
0x39dstore,AA...,v → ...,double 值从栈顶弹出,并赋值给本地变量表中索引为 AA 的本地变量
0x3aastore,AA...,v → ...,reference 值从栈顶弹出,并赋值给本地变量表中索引为 AA 的本地变量
0x3bistore_0...,v → ...,int 值从栈顶弹出,并赋值给本地变量表中索引为 0 的本地变量
0x3cistore_1...,v → ...,int 值从栈顶弹出,并赋值给本地变量表中索引为 1 的本地变量
0x3distore_2...,v → ...,int 值从栈顶弹出,并赋值给本地变量表中索引为 2 的本地变量
0x3eistore_3...,v → ...,int 值从栈顶弹出,并赋值给本地变量表中索引为 3 的本地变量
0x3flstore_0...,v → ...,long 值从栈顶弹出,并赋值给本地变量表中索引为 0 的本地变量
0x40lstore_1...,v → ...,long 值从栈顶弹出,并赋值给本地变量表中索引为 1 的本地变量
0x41lstore_2...,v → ...,long 值从栈顶弹出,并赋值给本地变量表中索引为 2 的本地变量
0x42lstore_3...,v → ...,long 值从栈顶弹出,并赋值给本地变量表中索引为 3 的本地变量
0x43fstore_0...,v → ...,float 值从栈顶弹出,并赋值给本地变量表中索引为 0 的本地变量
0x44fstore_1...,v → ...,float 值从栈顶弹出,并赋值给本地变量表中索引为 1 的本地变量
0x45fstore_2...,v → ...,float 值从栈顶弹出,并赋值给本地变量表中索引为 2 的本地变量
0x46fstore_3...,v → ...,float 值从栈顶弹出,并赋值给本地变量表中索引为 3 的本地变量
0x47dstore_0...,v → ...,double 值从栈顶弹出,并赋值给本地变量表中索引为 0 的本地变量
0x48dstore_1...,v → ...,double 值从栈顶弹出,并赋值给本地变量表中索引为 1 的本地变量
0x49dstore_2...,v → ...,double 值从栈顶弹出,并赋值给本地变量表中索引为 2 的本地变量
0x4adstore_3...,v → ...,double 值从栈顶弹出,并赋值给本地变量表中索引为 3 的本地变量
0x4bastore_0...,aref → ...,reference 值从栈顶弹出,并赋值给本地变量表中索引为 0 的本地变量
0x4castore_1...,aref → ...,reference 值从栈顶弹出,并赋值给本地变量表中索引为 1 的本地变量
0x4dastore_2...,aref → ...,reference 值从栈顶弹出,并赋值给本地变量表中索引为 2 的本地变量
0x4eastore_3...,aref → ...,reference 值从栈顶弹出,并赋值给本地变量表中索引为 3 的本地变量
0x4fiastore...,aaref,index,v → ...,aaref, index (int), v (int) 从栈顶弹出,并将 v 存入 aaref[index]
0x50lastore...,aaref,index,v → ...,aaref, index (int), v (long) 从栈顶弹出,并将 v 存入 aaref[index]
0x51fastore...,aaref,index,v → ...,aaref, index (int), v (float) 从栈顶弹出,并将 v 存入 aaref[index]
0x52dastore...,aaref,index,v → ...,aaref, index (int), v (double) 从栈顶弹出,并将 v 存入 aaref[index]
0x53aastore...,aaref,index,v → ...,aaref, index (int), v (reference) 从栈顶弹出,并将 v 存入 aaref[index]
0x54bastore...,aaref,index,v → ...,aaref, index (int), v (byte) 从栈顶弹出,并将 v 存入 aaref[index]
0x55castore...,aaref,index,v → ...,aaref, index (int), v (char) 从栈顶弹出,并将 v 存入 aaref[index]
0x56sastore...,aaref,index,v → ...,aaref, index (int), v (short) 从栈顶弹出,并将 v 存入 aaref[index]
0x57pop...,v → ...,将栈顶的值弹出
0x58pop2...,v2,v1 → ...,将栈顶的 1 或 2 个值弹出
0x59dup...,v → ...,v,v复制栈顶的值,并将复制的值压入栈顶
0x5adup_x1...,v2,v1 → ...,v1,v2,v1复制栈顶的值,并将复制的值插在栈顶往下的第 2 个位置
0x5bdup_x2...,v3,v2,v1 → ...,v1,v3,v2,v1复制栈顶的值,并将复制的值插在栈顶往下的第 2 或 3 个位置
0x5cdup2...,v2,v1 → ...,v2,v1,v2,v1复制栈顶的 1 或 2 个值,并将复制的值按原来的顺序压入栈顶
0x5ddup2_x1...,v3,v2,v1 → ...,v2,v1,v3,v2,v1复制栈顶的 1 或 2 个值,并将复制的值按原来的顺序插在栈顶往下的第 2 或 3个位置
0x5edup2_x2...,v4,v3,v2,v1 → ...,v2,v1,v4,v3,v2,v1复制栈顶的 1 或 2 个值,并将复制的值按原来的顺序插在栈顶往下的第 2、3 或 4 个位置
0x5fswap...,v2,v1 → ...,v1,v2交换栈顶的两个值
0x60iadd...,v1,v2 → ...,result将栈顶的两个 int 值相加,并将结果压入栈顶
0x61ladd...,v1,v2 → ...,result将栈顶的两个 long 值相加,并将结果压入栈顶
0x62fadd...,v1,v2 → ...,result将栈顶的两个 float 值相加,并将结果压入栈顶
0x63dadd...,v1,v2 → ...,result将栈顶的两个 double 值相加,并将结果压入栈顶
0x64isub...,v1,v2 → ...,result将栈顶的下一个 int 值减栈顶的 int 值,并将结果压入栈顶
0x65lsub...,v1,v2 → ...,result
0x66fsub...,v1,v2 → ...,result
0x67dsub...,v1,v2 → ...,result
0x68imul...,v1,v2 → ...,result
0x69lmul...,v1,v2 → ...,result
0x6afmul...,v1,v2 → ...,result
0x6bdmul...,v1,v2 → ...,result
0x6cidiv...,v1,v2 → ...,result
0x6dldiv...,v1,v2 → ...,result
0x6efdiv...,v1,v2 → ...,result
0x6fddiv...,v1,v2 → ...,result
0x70irem...,v1,v2 → ...,result
0x71lrem...,v1,v2 → ...,result
0x72frem...,v1,v2 → ...,result
0x73drem...,v1,v2 → ...,result
0x74ineg...,v1,v2 → ...,result
0x75lneg...,v1,v2 → ...,result
0x76fneg...,v1,v2 → ...,result
0x77dneg...,v1,v2 → ...,result
0x78ishl...,v1,v2 → ...,result
0x79lshl...,v1,v2 → ...,result
0x7aishr...,v1,v2 → ...,result
0x7blshr...,v1,v2 → ...,result
0x7ciushr...,v1,v2 → ...,result
0x7dlushr...,v1,v2 → ...,result
0x7eiand...,v1,v2 → ...,result
0x7fland...,v1,v2 → ...,result
0x80ior...,v1,v2 → ...,result
0x81lor...,v1,v2 → ...,result
0x82ixor...,v1,v2 → ...,result
0x83lxor...,v1,v2 → ...,result
0x84iinc,AA,+BB[^5]...,v → ...,result
0x85i2l...,v → ...,result
0x86i2f...,v → ...,result
0x87i2d...,v → ...,result
0x88l2i...,v → ...,result
0x89l2f...,v → ...,result
0x8al2d...,v → ...,result
0x8bf2i...,v → ...,result
0x8cf2l...,v → ...,result
0x8df2d...,v → ...,result
0x8ed2i...,v → ...,result
0x8fd2l...,v → ...,result
0x90d2f...,v → ...,result
0x91i2b...,v → ...,result
0x92i2c...,v → ...,result
0x93i2s...,v → ...,result
0x94lcmp...,v1,v2 → ...,result
0x95fcmpl...,v1,v2 → ...,result
0x96fcmpg...,v1,v2 → ...,result
0x97dcmpl...,v1,v2 → ...,result
0x98dcmpg...,v1,v2 → ...,result
0x99ifeq,+AAAA...,v1,v2 → ...,result
0x9aifne,+AAAA...,v1,v2 → ...,result
0x9biflt,+AAAA...,v1,v2 → ...,result
0x9cifge,+AAAA...,v1,v2 → ...,result
0x9difgt,+AAAA...,v1,v2 → ...,result
0x9eifle,+AAAA...,v1,v2 → ...,result
0x9fif_icmpeq,+AAAA...,v1,v2 → ...,result
0xa7goto,+AAAA
0xa0if_icmpne,+AAAA...,v1,v2 → ...,result
0xa1if_icmplt,+AAAA...,v1,v2 → ...,result
0xa2if_icmpge,+AAAA...,v1,v2 → ...,result
0xa3if_icmpgt,+AAAA...,v1,v2 → ...,result
0xa4if_icmple,+AAAA...,v1,v2 → ...,result
0xa5if_acmpeq,+AAAA...,v1,v2 → ...,result
0xa6if_acmpne,+AAAA...,v1,v2 → ...,result
0xa8jsr,+AAAA... → ...,address
0xa9ret,AA无变化
0xaatableswitch
[0]{0,3}
+AAAAAAAA
+BBBBBBBB
+CCCCCCCC
{+DDDDDDDD..+NNNNNNNN}
...,index → ...
0xablookupswitch
[0]{0,3}
+AAAAAAAA
+BBBBBBBB
+CCCCCCCC
{+DDDDDDDD..+NNNNNNNN}
...,key → ...
0xacireturn...,v → [empty]
0xadlreturn...,v → [empty]
0xaefreturn...,v → [empty]
0xafdreturn...,v → [empty]
0xb0areturn...,v → [empty]
0xb1return...,v → [empty]
0xb2getstatic,AAAA... → ...,v
0xb3putstatic,AAAA... → ...,v
0xb4getfield,AAAA...,aref → ...,v
0xb5putfield,AAAA...,aref → ...,v
0xb6invokevirtual,AAAA...,aref,[arg1,[arg2...]] → ...
0xb7invokespecial,AAAA...,aref,[arg1,[arg2...]] → ...
0xb8invokestatic,AAAA...,[arg1,[arg2...]] → ...
0xb9invokeinterface,AAAA,BB,00...,aref,[arg1,[arg2...]] → ...
0xbainvokedynamic,AAAA,00,00...,[arg1,[arg2...]] → ...
0xbbnew,AAAA... → ...,aref
0xbcnewarray,AA...,count → ...,aaref
0xbdanewarray,AAAA...,count → ...,aaref
0xbearraylength...,aaref → ...,length
0xbfathrow...,aref → ...,aref
0xc0checkcast,AAAA...,aref → ...,aref
0xc1instanceof,AAAA...,aref → ...,result
0xc2monitorenter...,aref → ...
0xc3monitorexit...,aref → ...
0xc4wide,<opcode>,AAAA,[BBBB]同原指令
0xc5multianewarray,AAAA,BB...,count1,[count2,...] → ...,aaref
0xc6ifnull,+AAAA...,v → ...
0xc7ifnonnull,+AAAA...,v → ...
0xc8goto_w,+AAAAAAAA无变化
0xc9jsr_w,+AAAAAAAA... → ...,address
0xcabreakpointJava debugger 预留
0xcb...预留
......预留
0xfd...预留
0xfeimpdep1为 debugger 预留
0xffimpdep2为 debugger 预留

[^1]: 用于存放操作数的栈结构,JVM 指令在执行的时候会从栈中取操作数,并将结果压回栈顶。栈还用于存放方法的参数(非静态方法的第一个参数是 this 引用),以及方法返回的结果。 [^2]: AA 表示 1 个无符号字节 (unsighed byte) [^3]: 直接编码在指令中并作为操作数使用的数据,如:bipush 0x100x10 被直接编码进指令序列中,即为立即数。 [^4]: AAAA 表示 1 个无符号 16 位整型 (unsighed 16-bit int) [^5]: +BB 表示 1 个有符号字节 (signed byte)