Java虚拟机之指令集

时间:2022-12-27 19:26:31

1 概述

Javac编译后的java文件的Code部分最终会保存在class文件的属性表集合的Code字段中。

Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的操作码(Opcode)以及跟随其后的零至多个代表此操作所需参数的操作数(Operands)所构成。

对于大部分为与数据类型相关的字节码指令,他们的操作码助记符中都有特殊的字符来表明专门为哪种数据类型服务:i代表对int类型的数据操作,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference。

2 加载和存储指令

  1. 将一个局部变量加载到操作栈的指令包括有:
    iload、iload_<n>、lload、lload_<n>、fload、fload_<n>、dload、dload_<n>、aload、aload_<n>

  2. 将一个数值从操作数栈存储到局部变量表的指令包括
    istore、istore_<n>、lstore、lstore_<n>、fstore、fstore_<n>、dstore、dstore_<n>、astore、astore_<n>

  3. 将一个常量加载到操作数栈的指令包括有
    bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、iconst_m1、iconst_<i>、lconst_<l>、fconst_<f>、dconst_<d>

  4. 扩充局部变量表的访问索引的指令:wide

3 运算指令

  1. 加法指令:iadd、ladd、fadd、dadd
  2. 减法指令:isub、lsub、fsub、dsub
  3. 乘法指令:imul、lmul、fmul、dmul
  4. 除法指令:idiv、ldiv、fdiv、ddiv
  5. 求余指令:irem、lrem、frem、drem
  6. 取反指令:ineg、lneg、fneg、dneg
  7. 位移指令:ishl、ishr、iushr、lshl、lshr、lushr
  8. 按位或指令:ior、lor
  9. 按位与指令:iand、land
  10. 按位异或指令:ixor、lxor
  11. 局部变量自增指令:iinc
  12. 比较指令:dcmpg、dcmpl、fcmpg、fcmpl、lcmp
      

4 类型转换指令

Java虚拟机对于宽化类型转换直接支持,并不需要指令执行,包括:

  1. int类型到long、float或者double类型
  2. long类型到float、double类型
  3. float类型到double类型

窄化类型转换指令包括有
i2b、i2c、i2s、l2i、f2i、f2l、d2i、d2l和d2f

窄化类型转换很可能会造成精度丢失。

5 对象创建与操作指令

  1. 创建类实例的指令:new
  2. 创建数组的指令:newarray,anewarray,multianewarray
  3. 访问类字段(static字段,或者称为类变量)和实例字段(非static字段,或者成为实例变量)的指令:getfield、putfield、getstatic、putstatic
  4. 把一个数组元素加载到操作数栈的指令:baload、caload、saload、iaload、laload、faload、daload、aaload
  5. 将一个操作数栈的值储存到数组元素中的指令:bastore、castore、sastore、iastore、fastore、dastore、aastore
  6. 取数组长度的指令:arraylength
  7. 检查类实例类型的指令:instanceof、checkcast
  8. 操作数栈管理指令(直接操作操作数栈的指令):pop、pop2、dup、dup2、dup_x1、dup2_x1、dup_x2、dup2_x2和swap

6 控制转移指令:

  1. 条件分支:ifeq、iflt、ifle、ifne、ifgt、ifge、ifnull、ifnonnull、if_icmpeq、if_icmpne、if_icmplt, if_icmpgt、if_icmple、if_icmpge、if_acmpeq和if_acmpne
  2. 复合条件分支:tableswitch、lookupswitch
  3. 无条件分支:goto、goto_w、jsr、jsr_w、ret

7 方法调用和返回指令

  1. invokevirtual指令用于调用对象的实例方法,根据对象的实际类型进行分派(虚方法分派),这也是Java语言中最常见的方法分派方式。
  2. invokeinterface指令用于调用接口方法,它会在运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用。
  3. invokespecial指令用于调用一些需要特殊处理的实例方法,包括实例初始化方法、私有方法和父类方法。
  4. invokestatic指令用于调用类方法(static方法)
  5. invokedynamic指令用于调用以绑定了invokedynamic指令的调用点对象(call site object)作为目标的方法。调用点对象是一个特殊的语法结构,当一条invokedynamic指令首次被Java虚拟机执行前,Java虚拟机将会执行一个引导方法(bootstrap method)并以这个方法的运行结果作为调用点对象。因此,每条invokedynamic指令都有独一无二的链接状态,这是它与其他方法调用指令的一个差异。
  6. 方法返回指令则是根据返回值的类型区分的,包括有

    1. ireturn(当返回值是boolean、byte、char、short和int类型时使用)
    2. lreturn(long)、freturn(float)、dreturn(double)和areturn(reference)
    3. return指令供声明为void的方法、实例初始化方法、类和接口的类初始化方法使用

8 抛出异常指令

athrow

还可以参考这里给出的详细指令码说明http://blog.csdn.net/lm2302293/article/details/6713147