声明:本文只做字节码介绍,不会谈其底层原理
JVM 指令集中的类型支持
- opcode: (指令)操作码,首字母 T 代表指定类型 (Type),例如 byte 的 Tipush 是 bipush, "/" 说明暂不支持该类型
opcode | byte | short | int | long | float | double | char | reference |
---|---|---|---|---|---|---|---|---|
Tipush | bipush | sipush | / | / | / | / | / | / |
Tconst | / | / | iconst | lconst | fconst | dconst | / | aconst |
Tload | / | / | iload | lload | fload | dload | / | aload |
Tstore | / | / | istore | lstore | fstore | dstore | / | astore |
Tinc | / | / | iinc | / | / | / | / | / |
Taload | baload | saload | iaload | laload | faload | daload | caload | aaload |
Tastore | bastore | sastore | iastore | lastore | fastore | dastore | castore | aastore |
Tadd | / | / | iadd | ladd | fadd | dadd | / | / |
Tsub | / | / | isub | lsub | fsub | dsub | / | / |
Tmul | / | / | imul | lmul | fmul | dmul | / | / |
Tdiv | / | / | idiv | ldiv | fdiv | ddiv | / | / |
Trem | / | / | irem | lrem | frem | drem | / | / |
Tneg | / | / | ineg | lneg | fneg | dneg | / | / |
Tshl | / | / | ishl | lshl | / | / | / | / |
Tshr | / | / | ishr | lshr | / | / | / | / |
Tushr | / | / | iushr | lushr | / | / | / | / |
Tand | / | / | iand | land | / | / | / | / |
Tor | / | / | ior | lor | / | / | / | / |
Txor | / | / | ixor | lxor | / | / | / | / |
i2T | i2b | i2s | / | i2l | i2f | i2d | / | / |
l2T | / | / | l2i | l2f | l2d | / | / | |
f2T | / | / | f2i | f2l | / | f2d | / | / |
d2T | / | / | d2i | d2l | d2f | / | / | / |
Tcmp | / | / | / | lcmp | / | / | / | / |
Tcmpl | / | / | / | / | fcmpl | dcmpl | / | / |
Tcmpg | / | / | / | / | fcmpg | dcmpg | / | / |
if_TcmpOP | / | / | if_icmpOP | / | / | / | / | if_acmpOP |
Treturn | / | / | ireturn | lreturn | freturn | dreturn | / | areturn |
JVM 中的实际类型和计算类型映射关系一览表
- Actual type: JVM 实际类型
- Computational type: JVM 计算类型
- Category: 虚拟机类型
Actual type | Computational type | Category |
---|---|---|
boolean | int | 32-bit |
byte | int | 32-bit |
char | int | 32-bit |
short | int | 32-bit |
int | int | 32-bit |
float | float | 32-bit |
reference | reference | 32-bit |
returnAddress | returnAddress | 32-bit |
long | long | 64-bit |
double | double | 64-bit |
Load 和 Store 指令
由于指令较多且大同小异,就不一一翻译了,详情请见参考链接,以下同理
load 和 store 指令用于在 JVM 栈帧的局部变量和操作数栈之间进行值的传递
- load 一个局部变量到操作数栈顶部:
iload, iload_<n>, lload, lload_<n>, fload, fload_<n>, dload, dload_<n>, aload, aload_<n>.
- load 一个常量到操作数栈顶部:
bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, iconst_m1, iconst_<i>, lconst_<l>, fconst_<f>, dconst_<d>.
- store 一个操作数栈的值到一个局部变量中:
istore, istore_<n>, lstore, lstore_<n>, fstore, fstore_<n>, dstore, dstore_<n>, astore, astore_<n>.
算术指令
算数指令通常用于计算操作数栈顶的两个值,并将计算结果返回到操作数栈。主要有整数类和浮点类计算,像 boolean,byte,short 和 char 也是被当作 int 来进行计算的
-
Add: iadd, ladd, fadd, dadd
-
Subtract: isub, lsub, fsub, dsub
-
Multiply: imul, lmul, fmul, dmul
-
Divide: idiv, ldiv, fdiv, ddiv
-
Remainder: irem, lrem, frem, drem
-
Negate: ineg, lneg, fneg, dneg
-
Shift: ishl, ishr, iushr, lshl, lshr, lushr
将栈顶第二个数向左/右移栈顶第一个数的低五位值的量。例如 ishl:若栈顶第一个数为 100, 第二个数为 10, 则将 10 左移 100 的低五位值的量 (100 的二进制为 01100100,低五位则为 4,低五位最大值为 32), 将其结果 160 放回栈顶
-
Bitwise OR: ior, lor
-
Bitwise AND: iand, land
-
Bitwise exclusive OR: ixor, lxor
-
Local variable increment: iinc
-
Comparison: dcmpg, dcmpl, fcmpg, fcmpl, lcmp
类型转换指令
JVM 支持以下两类字节转换
- 小转大
- float to doubles: f2d
- long to float, double: l2f, l2d
- int to long, float, double: i2l, i2f, i2d
- 大转小
- long to int: l2i
- float to int or long: f2i, f2l
- int to byte, short, or char:i2b,i2s, i2c
- double to int, long, or float: d2i, d2l,d2f
对象创建和操作
- 新建实例对象:new
- 获取数组长度:arraylength
- 访问类字段,即静态字段:getstatic, putstatic
- 检查类实例对象和数组:instanceof, checkcast
- 访问实例字段,即非静态字段:getfield, putfield
- 新建数组::newarray, anewarray, multianewarray
- 将数组加载到操作数栈:baload, caload, saload, iaload, laload, faload, daload, aaload
- 将操作数中的值存储为数组:bastore, castore,sastore, iastore, lastore, fastore, dastore, aastore
操作数栈管理指令
因为操作数栈的结构是栈,所以关于它的操作都离不开出栈入栈,LIFO
pop, pop2, dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2, swap
控制转移指令
- 条件分支(满足一定条件):ifeq, ifne, iflt, ifle, ifgt, ifge, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmplt, if_icmple, if_icmpgt if_icmpge, if_acmpeq, if_acmpne
- 复合条件分支(满足一定复合条件):tableswitch, lookupswitch
- 无条件分支(无需满足条件):goto, goto_w, jsr, jsr_w, ret
- 另外,同算术指令一样,非浮点基础类型使用 int 进行分支判断,且为有符号 int
方法调用和返回指令
- invokevirtual: 调用实例对象的方法,对对象的类型进行调度,Java 默认的方法调度指令
- invokeinterface: 调用接口方法,在运行时查找正确的方法进行调用
- invokespecial: 调用特定的方法,包括实例对象的
<init>
类的<clinit>
和签名多态方法
异常抛出
抛出异常的指令为 athrow ,另外,如果 JVM 检测到异常,也会抛出
同步
针对不同的同步对象,编译后的字节码是不一样的,但是其本质都是一样的,都是依赖 monitor 的状态
对于实例方法和静态方法的同步:ACC_SYNCHRONIZED
对于代码块或实例对象的同步:monitorenter, monitorexit