Java虚拟机的指令由
一个字节长度
(u1)、代表着某种特定操作含义的数字(操作码
,Opcode)以及跟随其后的零至多个代表此操作所需参数(操作数
,Operands)而构成。
Java虚拟机采用面向操作数栈
而不是寄存器的架构,大多数指令都不包含操作数,只有一个操作码。
大部分指令都没有支持byte、char、short、boolean类型。是因为编译器在编译期或运行期将byte、short类型直接
带符号扩展(Sign-Extend)
,对boolean、char类型零位扩展(Zero-Extend)
。
因此在实际操作时都是使用相应的int类型作为运算类型。
指令分为
1、加载和存储指令
:用于将数据在栈帧中的局部变量表和操作数栈之间来回传输。
比如iload_<n>, istore_<n>, iconst_<i>, wide等
2、运算指令
:对两个操作数栈上的值进行某种特定运算,并重新存入到操作数栈顶。
如iadd, isub, idiv, imul, irem, ineg, ior, ishl, iinc, dcmog(比较)等
3、类型转换指令
:将两种不同的数值类型进行相互转换,这些转换操作一般用于实现用户代码中的显示类型转换操作,或者用来处理字节码指令集中数据类型相关指令无法与数据类型一一对应的问题。
如i2b, i2c, i2s等
进行窄化类型转换的时候,可能导致转换结果产生不同的正负号(简单丢弃多出的高位)、不同的数量级的情况,转换过程很可能会导致数值的精度丢失。
另外浮点值NaN会转换成整型的0。
4、对象创建与访问指令
:类实例和数组的创建和操作使用不同的指令。
创建类实例:new;
创建数组:newarray、anewarray、multianewarray;
访问类字段和实例字段:getfield、getstatic等;
数组元素加载到操作数栈:iaload等;
操作数栈的值加载到数元素中:iastore等;
取数组长度:arraylength;
检查类实例类型:instanceof、checkcast。
5、操作数栈管理指令
:直接操作操作数栈。
出栈:pop,pop2;
入栈:dup,dup2等;
交换:swap。
6、控制转移指令
:让Java虚拟机有条件
或无条件
地从指定的位置指令而不是控制转移指令的吓一跳继续执行指令。即修改PC寄存器的值。
条件分支:ifeq、iflt、ifnull、if_cmpeq等;
复合条件分支:tableswitch、lookupswitch;
无条件分支:goto、jsr、ret等。
7、方法调用和返回指令
:
invokevirtual调用对象的实例方法;
invokeinterface调用接口方法;
inokespecial调用需要特殊处理的方法,你如实例初始化方法、私有方法和父类方法等;
invokestatic调用类方法;
invokedynamic在运行时动态解析出调用点限定符所引用的方法,并执行该方法;
返回指令:return、ireturn等。
8、异常处理指令
:
显式
抛出异常的操作(throw语句)都由athrow
指令来实现。
9、同步指令
:支持synchronized方法块的同步
Java虚拟机支持方法级的同步以及方法内部一段指令的同步。使用管程(Monitor)来支持。
使用monitorenter和moniterexit两条指令来支持synchronized关键字的语义。
另外,为了保证在方法异常完成时monitorenter和monitorexit指令依然可以正确配对执行,编译器会自动产生一个异常处理器,这个异常处理器声明可以处理所有的异常,目的就是用来执行monitorexit指令。
网友评论