zhaoyu@home:~$

jvm-指令集总结

类型相关

JVM中大多数指令和类型相关,如iload指令只能操作int类型到操作数栈,两种指令可能有相同的实现。但是有opcodes不同。 下图总结了JVM指令集支持的类型。

我们注意到,大部分操作没有整数类型byte,char,short。没有boolean类型的任何操作。在编译期或运行时,JVM加载byte和short的字面值时, 会扩展为int类型的值;boolean和char的字面值会使用指令扩展为int类型的值,对于的数据中的元素也会做扩展。

load和store指令

load和store命令用于在一个栈帧中的本地变量表和操作栈之间转移值。 load将本地变量表中的值转移到操作栈,store相反。

  • load将本地变量表中的值转移到操作栈:iload,iload_<n>等。
  • store从操作栈转移到本地变量表:istore,istore_<n>等。
  • 将一个常量加载到操作栈:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null, iconst_m1, iconst_<i>, lconst_<l>, fconst_<f>, dconst_<d>
  • 访问更多的本地变量或更大的操作数:wide
    访问对象字段和数组元素的指令也可以和操作栈之间转移数据。
    指令iload_<n>包含了(iload_0,iload_1,iload_2,iload_3),其中n为本地变量表的下标。

算数指令

  • 加:iadd, ladd, fadd, dadd。
  • 减:isub, lsub, fsub, dsub。
  • 乘:imul, lmul, fmul, dmul。
  • 除:idiv, ldiv, fdiv, ddiv。
  • 取余:irem, lrem, frem, drem。
  • 取反: ineg, lneg, fneg, dneg。
  • 位移: ishl, ishr, iushr, lshl, lshr, lushr。
  • 位或: ior, lor。
  • 位与 iand, land。
  • 位异或: ixor, lxor。
  • 自增: iinc。
  • 比较:dcmpg, dcmpl, fcmpg, fcmpl, lcmp。

类型转换指令

宽化转换包括:i2l, i2f, i2d, l2f, l2d, and f2d。 窄化转换包括:i2b, i2c, i2s, l2i, f2i, f2l, d2i, d2l, and d2f。

对象创建

  • 创建一个对象实例:new。
  • 创建一个数组实例:newarray, anewarray, multianewarray。
  • 访问静态字段:getstatic, putstatic;访问实例字段:getfield, putfield。
  • 加载数组元素到操作栈:baload, caload, saload, iaload, laload, faload, daload, aaload。
  • 将操作栈的值存储为数组元素:bastore, castore, sastore, iastore, lastore, fastore, dastore, aastore。
  • 获取数组长度:arraylength。
  • 获取类实例或数组的属性:instanceof,checkcast。

操作栈管理

操作栈的指令包括:pop, pop2, dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2, swap。

  1. dup:复制栈顶部的一个字长的内容。
    栈: 前:……,word 后:……,word,word
  2. dup_x1:复制栈顶部一个字长的内容,然后将复制内容插入到栈顶(1+1)个字长下面。
    栈: 前:……,word2,word1 后:……,word1,word2,word1
  3. dup_x2:复制栈顶部一个字长的内容,然后将复制内容插入到栈顶(1+2)个字长下面。
    栈: 前:…….,word3,word2,word1 后:…….,word1,word3,word2,word1
  4. dup2:复制栈顶部长度为两个字长的内容
    栈: 前:……,word2,word1 后:……,word2,word1,word2,word1 dup2_x1,dup2_x1 类似。long和double占两个字长,其他类型占一个字长,要注意

控制转换

  • 条件分支: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。

方法调用和返回

  • invokevirtual:调用对象的实例方法。
  • invokeinterface:调用接口方法,查找所有被运行时对象实现的方法,并确定对应的方法。
  • invokespecial:调用需要特殊处理的实例方法,包括实例初始化方法,private方法,或者父类方法。
  • invokestatic:调用静态方法。
  • invokedynamic:由用户动态分派调用,会转到bootstrap方法。bootstrap可以动态获取参数类型,然后可以根据类型分配给合适的方法,让 jvm实现动态语言的方法调用。

抛出异常

使用athrow指令。

同步

JVM使用同步monitor支持方法和方法内的指令序列两种同步。
方法级别的同步隐式执行的。一个synchronized方法会在运行时常量池的method_info中被ACC_SYNCHRONIZED标记。
指令序列的同步通常是使用了synchronized代码块。JVM使用monitorentermonitorexit支持。
monitor的进入和退出是由JVM自动执行的。