JVM 字节码

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)
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计