JVM 字节码
注:指令按「功能大类」划分,同一类内按使用频率排序,每个指令包含「格式」「作用」「使用场景」,结合实际代码案例便于理解。
一、数据操作指令(最常用,占字节码总量 60%+)
1. 局部变量操作指令(操作方法内的局部变量,如参数、临时变量)
| 指令格式 |
作用 |
使用场景举例 |
| iload_n(n=0-3) |
加载第 n 个局部变量(int/boolean 类型)到操作数栈 |
int a=1; 中加载a(iload_1) |
| istore_n(n=0-3) |
从操作数栈存 int/boolean 值到第 n 个局部变量 |
a=2; 中存值到a(istore_1) |
| aload_n(n=0-3) |
加载第 n 个局部变量(引用类型,如对象 / 数组)到操作数栈 |
int[] arr=new int[3]; 加载arr(aload_1) |
| astore_n(n=0-3) |
从操作数栈存引用值到第 n 个局部变量 |
arr=new int[3]; 存arr到局部变量(astore_1) |
| iload index |
加载指定索引(>3)的 int/boolean 局部变量 |
局部变量超过 4 个时使用(如iload 4) |
| aload index |
加载指定索引(>3)的引用局部变量 |
局部变量超过 4 个时使用(如aload 5) |
2. 常量操作指令(往操作数栈压入常量值)
| 指令格式 |
作用 |
使用场景举例 |
| iconst_n(n=-1~5) |
压入 int 常量 n(boolean 用 1=true/0=false) |
return true;(iconst_1)、int a=3;(iconst_3) |
| lconst_n(n=0/1) |
压入 long 常量 n(占 2 个操作数栈位置) |
long b=1L;(lconst_1) |
| fconst_n(n=0-2) |
压入 float 常量 n |
float c=2.0f;(fconst_2) |
| dconst_n(n=0/1) |
压入 double 常量 n(占 2 个操作数栈位置) |
double d=1.0;(dconst_1) |
| ldc 常量 |
压入 int/long/float/double/ 字符串常量(从常量池取) |
String s=“abc”;(ldc “abc”)、int a=100;(ldc 100) |
| ldc2_w 常量 |
压入 long/double 常量(常量池索引 > 255 时用) |
long e=1000L;(ldc2_w 1000L) |
3. 数组操作指令(操作数组的创建、赋值、取值)
| 指令格式 |
作用 |
使用场景举例 |
| newarray 类型 |
创建一维基本类型数组(如 int/char) |
int[] arr=new int[3];(iconst_3→newarray int) |
| anewarray 类 |
创建一维引用类型数组(如 Object []/int [][]) |
int[][] grid=new int[3][];(iconst_3→anewarray “[I”) |
| iaload |
从 int 数组中取元素(数组引用 + 索引→元素值) |
int a=arr[2];(aload_1→iconst_2→iaload) |
| iastore |
往 int 数组中存元素(数组引用 + 索引 + 值→存值) |
arr[2]=5;(aload_1→iconst_2→iconst_5→iastore) |
| aaload |
从引用数组中取元素(如 int [][] 取某一行) |
int[] row=grid[0];(aload_1→iconst_0→aaload) |
| aastore |
往引用数组中存元素(如 int [][] 存某一行) |
grid[0]=new int[3];(aload_1→iconst_0→aload_2→aastore) |
| arraylength |
获取数组长度(数组引用→长度值) |
int len=arr.length;(aload_1→arraylength→istore_2) |
| multianewarray 类 维度 |
创建多维数组(如 int [2][3]) |
较少用,int[][][] arr=new int[2][3][4];(iconst_2→iconst_3→iconst_4→multianewarray “[[[I” 3) |
二、算术与逻辑指令(常用,处理数值计算和比较)
1. 算术指令(int/long/float/double 类型的加减乘除)
| 指令格式 |
作用 |
使用场景举例 |
| iadd |
操作数栈顶两个 int 值相加(a+b→结果压栈) |
int c=a+b;(iload_1→iload_2→iadd→istore_3) |
| isub |
操作数栈顶两个 int 值相减(a-b→结果压栈) |
int c=a-b;(iload_1→iload_2→isub→istore_3) |
| imul |
操作数栈顶两个 int 值相乘(a*b→结果压栈) |
int c=a*b;(iload_1→iload_2→imul→istore_3) |
| idiv |
操作数栈顶两个 int 值相除(a/b→结果压栈,整除) |
int c=a/b;(iload_1→iload_2→idiv→istore_3) |
| irem |
操作数栈顶两个 int 值取余(a% b→结果压栈) |
int c=a%b;(iload_1→iload_2→irem→istore_3) |
| ladd/lsub |
long 类型的加减(占 2 个操作数栈位置) |
long c=a+b;(lload_1→lload_2→ladd→lstore_3) |
| fadd/dadd |
float/double 类型的加法 |
较少用,float c=a+b;(fload_1→fload_2→fadd→fstore_3) |
2. 比较指令(比较操作数栈顶值,结果用于分支跳转)
| 指令格式 |
作用(int 类型,其他类型类似:lcmp/fcmpg 等) |
使用场景举例 |
| if_icmpeq 目标行 |
比较两个 int 值:相等则跳转到目标行 |
if(a==b) { … }(iload_1→iload_2→if_icmpeq 10) |
| if_icmpne 目标行 |
比较两个 int 值:不相等则跳转到目标行 |
if(a!=b) { … }(iload_1→iload_2→if_icmpne 10) |
| if_icmplt 目标行 |
比较两个 int 值:a<b 则跳转到目标行 |
if(a<b) { … }(iload_1→iload_2→if_icmplt 10) |
| if_icmpge 目标行 |
比较两个 int 值:a>=b 则跳转到目标行 |
for(int i=0;i<len;i++)(iload_1→iload_2→if_icmpge 20) |
| ifeq 目标行 |
比较 int 值与 0:等于 0 则跳转 |
if(flag==false) { … }(iload_1→ifeq 10,因 false=0) |
| ifne 目标行 |
比较 int 值与 0:不等于 0 则跳转 |
if(flag==true) { … }(iload_1→ifne 10,因 true=1) |
| acmp_eq 目标行 |
比较两个引用类型:地址相等则跳转 |
if(obj1==obj2) { … }(aload_1→aload_2→if_acmpeq 10) |
三、分支与循环指令(常用,控制代码执行流程)
| 指令格式 |
作用 |
使用场景举例 |
| goto 目标行 |
无条件跳转到目标行(不依赖条件) |
while(true) { … }(循环体结束→goto 5) |
| if_icmpne 目标行 |
见「比较指令」,常用于 if/for 条件判断 |
if(a!=1) return false;(iload_1→iconst_1→if_icmpne 7) |
| tableswitch |
按 int 值跳转(用于 switch-case,值连续时) |
switch(a) { case 1: … case 2: … } |
| lookupswitch |
按 int 值跳转(用于 switch-case,值不连续时) |
switch(a) { case 1: … case 100: … } |
四、方法调用与返回指令(常用,调用方法和返回结果)
1. 方法调用指令(按调用类型排序,静态方法最常用)
| 指令格式 |
作用 |
使用场景举例 |
| invokestatic 类.方法 |
调用静态方法(无 this) |
Math.min(a,b)(iload_1→iload_2→invokestatic java/lang/Math.min:(II)I) |
| invokevirtual 类.方法 |
调用实例方法(有 this,动态绑定) |
System.out.println(a)(getstatic→iload_1→invokevirtual java/io/PrintStream.println:(I)V) |
| invokespecial 类.方法 |
调用特殊方法(构造方法、private 方法、super 方法) |
构造方法(aload_0→invokespecial java/lang/Object."":()V) |
| invokeinterface 接口.方法 |
调用接口方法(动态绑定) |
较少用,List.add(obj)(aload_1→aload_2→invokeinterface java/util/List.add:(Ljava/lang/Object;)Z) |
| invokedynamic 引导方法 |
调用动态方法(Lambda/Stream 用) |
Java 8 + 特性,List.forEach(System.out::println) |
2. 方法返回指令(按返回值类型排序)
| 指令格式 |
作用 |
使用场景举例 |
| ireturn |
返回 int/boolean 类型结果 |
return true;(iconst_1→ireturn)、return 5;(iconst_5→ireturn) |
| lreturn |
返回 long 类型结果 |
return 100L;(lconst_1→lreturn) |
| freturn |
返回 float 类型结果 |
return 2.0f;(fconst_2→freturn) |
| dreturn |
返回 double 类型结果 |
return 3.0;(dconst_1→dreturn) |
| areturn |
返回引用类型结果(对象 / 数组 / 字符串) |
return arr;(aload_1→areturn) |
| return |
无返回值(void 方法) |
void func() { … }(方法结束→return) |
五、类型相关指令(较常用,处理类型转换、静态变量)
| 指令格式 |
作用 |
使用场景举例 |
| i2l/i2f/i2d |
int 转 long/float/double(宽转换,无溢出) |
long a=1;(iconst_1→i2l→lstore_1) |
| l2i/f2i/d2i |
long/float/double 转 int(窄转换,可能溢出) |
int a=(int)100L;(lconst_1→l2i→istore_1) |
| checkcast 类 |
检查引用类型强制转换是否合法(如 Object→String) |
String s=(String)obj;(aload_1→checkcast java/lang/String→astore_2) |
| instanceof 类 |
判断引用是否为某类 / 接口的实例(返回 boolean) |
if(obj instanceof String) { … }(aload_1→instanceof java/lang/String→ifne 10) |
| getstatic 类.字段 |
获取静态变量值(如 System.out) |
PrintStream out=System.out;(getstatic java/lang/System.out:Ljava/io/PrintStream;→astore_1) |
| putstatic 类.字段 |
给静态变量赋值(如 Math.PI 不可用,用自定义静态变量) |
MyClass.count=5;(iconst_5→putstatic com/xxx/MyClass.count:I) |
六、异常与同步指令(不常用,处理异常和线程安全)
| 指令格式 |
作用 |
使用场景举例 |
| athrow |
抛出异常对象(如 throw new Exception ()) |
throw new RuntimeException();(new→dup→invokespecial→athrow) |
| monitorenter |
获取对象监视器锁(synchronized 代码块入口) |
synchronized(obj) { … }(aload_1→monitorenter) |
| monitorexit |
释放对象监视器锁(synchronized 代码块出口) |
synchronized 代码块结束→aload_1→monitorexit |
| jsr 目标行 |
跳转到异常处理代码(Java 6 前用,现已被异常表替代) |
极少用,现代字节码用「异常表」记录异常处理逻辑 |
七、栈操作指令(较常用,操作操作数栈)
| 指令格式 |
作用 |
使用场景举例 |
| dup |
复制操作数栈顶元素(常用于对象创建后调用构造方法) |
new Object()(new→dup→invokespecial) |
| dup_x1 |
复制栈顶元素,插入到栈顶下第 1 个元素前 |
较少用,复杂栈操作(如a,b→a,b,a) |
| pop |
弹出操作数栈顶元素(丢弃,无返回) |
不需要的计算结果(如a+b;→iadd→pop) |
| pop2 |
弹出栈顶 2 个元素(用于 long/double) |
long a=1L;→lconst_1→pop2(丢弃 a) |