记载和内存指令是用于将数据在栈帧中的局部变量表和操作数栈之间来回传输
将局部变量表加载到操作数栈:iload lload fload dload aload
将一个数值从操作数占存储到局部变量表: istore lfda
将一个常量加载到操作数栈: bipush sipush ldc ldc_w ldc2_w aconst_null iconst_m1 iconst_m1
扩充局部变量表的访问索引的指令: wide
运算指令
运算或算术指令用于对两个操作数栈上的值进行某种特定的运算,并把结果存储到操作数栈顶
加法指令: add
减法指令: sub
乘法指令: mul
除法指令: div
取余指令: rem
取反指令: neg
类型转化指令
类型转化指令可以将两种不同的数值类型进行相互转换,这些转换操作一般用户实现用户代码中的显示类型转换操作以及用来处理字节码指令集中数据类型相关指令无法与数据类型一一对应的问题
宽化类型处理和窄化类型处理
l2b i2c i2s l2i ....
对象创建与访问指令
创建类实例指令: new
创建数组的指令: newarray anewarray multianewarray
把数组元素加载到操作数栈的指令: baload c s I l f d a
将操作数栈的值存储到数组元素: astore
取数组长度指令: arraylength
检查实例类型的指令: instanceof checkcast
操作树栈管理指令
操作数栈指令用于直接操作操作数栈
将操作数栈的一个或两个元素出栈: pop pop2
复制栈顶一个或两个数值并将复制或双份复制值重新压入栈顶: dup dup2 dup_x1 dup_x2
将栈顶的两个数值替换: swap
控制转移指令
控制转移指令可以让Java虚拟机有条件或无条件的从指定的位置指令而不是控制转移指令的下一条指令继续执行程序。可以认为控制转移指令就是在修改pc寄存器的值。
条件分支: ifeq iflt ifle ifne ifgt ifnull ifcmple
复合条件分支: tableswitch lookupswitch
无条件分支Lgoto goto_w jsr jsr_w ret
方法调用指令
invokevitual指令用于调用对象的实例方法,根据对象的实际类型进行分派(虚方法分派),这也是Java语言中最常见的方法分派方式
invokeinterface指令用于调用接口方法,它会在运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用
invokespecial指令用于调用一些需要特殊处理的实例方法,包括实例初始化方法、私有方法和父类方法
invokestatic指令用于调用类方法(static方法)
异常处理指令
在程序中显示抛出异常的操作会由athrow指令实现,除了这种情况,还有别的异常会在其他的Java虚拟机指令检测到异常状况时由虚拟机自动抛出
同步指令
Java虚拟机可以支持方法级的同步和方法内部一段指令序列的同步,这两种同步结构都是使用管程(Monitor)来支持的。
方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操作之中。虚拟机可以从方法常量池中的方法表结构(method info Structure)中的ACC_SYNCHRONIZED访问标志区分一个方法是否是同步方法。当方法调用时,调用指令将会检查方法的SCC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程将先持有管程,然后再执行方法,最后再方法完成(无论是正常完成还是非正常完成)时释放管程。在方法执行期间,执行线程持有了管程,其他任何线程都无法再获得同一个管程。如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那这个同步方法所持有的管程将在异常跑到同步方法之外时自动释放。
同步一段指令集序列通常是由Java语言中的synchronized块来表示的,Java虚拟机的指令集中有monitorenter和monitorexit两条指令来支持synchronized关键字语义,争取实现synchronized关键字需要编译器与Java虚拟机二者写作支持
JVM指令集(指令码、助记符、功能描述)
指令码 |
助记符 |
功能描述 |
||||||||||||
0x00 |
nop |
无操作 |
||||||||||||
|
||||||||||||||
0x01 |
aconst_null |
指令格式: aconst_null
功能描述: null进栈。
注意:JVM并没有为null指派一个具体的值。
|
||||||||||||
|
||||||||||||||
0x02 |
iconst_m1 |
int型常量值-1进栈 |
||||||||||||
0x03 |
iconst_0 |
int型常量值0进栈 |
||||||||||||
0x04 |
iconst_1 |
int型常量值1进栈 |
||||||||||||
0x05 |
iconst_2 |
int型常量值2进栈 |
||||||||||||
0x06 |
iconst_3 |
int型常量值3进栈 |
||||||||||||
0x07 |
iconst_4 |
int型常量值4进栈 |
||||||||||||
0x08 |
iconst_5 |
int型常量值5进栈 |
||||||||||||
|
||||||||||||||
0x09 |
lconst_0 |
long型常量值0进栈 |
||||||||||||
0x0A |
lconst_1 |
long型常量值1进栈 |
||||||||||||
|
||||||||||||||
0x0B |
fconst_0 |
float型常量值0进栈 |
||||||||||||
0x0C |
fconst_1 |
float型常量值1进栈 |
||||||||||||
0x0D |
fconst_2 |
float型常量值2进栈 |
||||||||||||
|
||||||||||||||
0x0E |
dconst_0 |
double型常量值0进栈 |
||||||||||||
0x0F |
dconst_1 |
double型常量值1进栈 |
||||||||||||
|
||||||||||||||
0x10 |
bipush |
将一个byte型常量值推送至栈顶 |
||||||||||||
0x11 |
sipush |
将一个short型常量值推送至栈顶 |
||||||||||||
|
||||||||||||||
0x12 |
ldc |
将int、float或String型常量值从常量池中推送至栈顶 |
||||||||||||
0x13 |
ldc_w |
将int、float或String型常量值从常量池中推送至栈顶(宽索引) |
||||||||||||
0x14 |
ldc2_w |
将long或double型常量值从常量池中推送至栈顶(宽索引) |
||||||||||||
|
||||||||||||||
0x15 |
iload |
指定的int型局部变量进栈 |
||||||||||||
0x16 |
lload |
指定的long型局部变量进栈 |
||||||||||||
0x17 |
fload |
指定的float型局部变量进栈 |
||||||||||||
0x18 |
dload |
指定的double型局部变量进栈 |
||||||||||||
0x19 |
aload |
指令格式: aload index
功能描述: 当前frame的局部变量数组中下标为 index的引用型局部变量进栈
index : 无符号一byte整型。和wide指令联用, 可以使index为两byte。
|
||||||||||||
|
||||||||||||||
0x1A |
iload_0 |
第一个int型局部变量进栈 |
||||||||||||
0x1B |
iload_1 |
第二个int型局部变量进栈 |
||||||||||||
0x1C |
iload_2 |
第三个int型局部变量进栈 |
||||||||||||
0x1D |
iload_3 |
第四个int型局部变量进栈 |
||||||||||||
|
||||||||||||||
0x1E |
lload_0 |
第一个long型局部变量进栈 |
||||||||||||
0x1F |
lload_1 |
第二个long型局部变量进栈 |
||||||||||||
0x20 |
lload_2 |
第三个long型局部变量进栈 |
||||||||||||
0x21 |
lload_3 |
第四个long型局部变量进栈 |
||||||||||||
|
||||||||||||||
0x22 |
fload_0 |
第一个float型局部变量进栈 |
||||||||||||
0x23 |
fload_1 |
第二个float型局部变量进栈 |
||||||||||||
0x24 |
fload_2 |
第三个float型局部变量进栈 |
||||||||||||
0x25 |
fload_3 |
第四个float型局部变量进栈 |
||||||||||||
|
||||||||||||||
0x26 |
dload_0 |
第一个double型局部变量进栈 |
||||||||||||
0x27 |
dload_1 |
第二个double型局部变量进栈 |
||||||||||||
0x28 |
dload_2 |
第三个double型局部变量进栈 |
||||||||||||
0x29 |
dload_3 |
第四个double型局部变量进栈 |
||||||||||||
|
||||||||||||||
0x2A |
aload_0 |
指令格式:aload_0
该指令的行为类似于aload指令index为0的情况。
|
||||||||||||
0x2B |
aload_1 |
同上
|
||||||||||||
0x2C |
aload_2 |
同上
|
||||||||||||
0x2D |
aload_3 |
同上
|
||||||||||||
|
||||||||||||||
0x2E |
iaload |
指定的int型数组的指定下标处的值进栈 |
||||||||||||
0x2F |
laload |
指定的long型数组的指定下标处的值进栈 |
||||||||||||
0x30 |
faload |
指定的float型数组的指定下标处的值进栈 |
||||||||||||
0x31 |
daload |
指定的double型数组的指定下标处的值进栈 |
||||||||||||
0x32 |
aaload |
指令格式: aaload
功能描述: 栈顶的数组下标(index)、数组引用 (arrayref)出栈,并根据这两个数值 取出对应的数组元素值(value)进栈。
抛出异常: 如果arrayref的值为null,会抛出 NullPointerException。 如果index造成数组越界,会抛出 ArrayIndexOutOfBoundsException。
index : int类型 arrayref : 数组的引用
|
||||||||||||
0x33 |
baload |
指定的boolean或byte型数组的指定下标处的值进栈 |
||||||||||||
0x34 |
caload |
指定的char型数组的指定下标处的值进栈 |
||||||||||||
0x35 |
saload |
指定的short型数组的指定下标处的值进栈 |
||||||||||||
|
||||||||||||||
0x36 |
istore |
将栈顶int型数值存入指定的局部变量 |
||||||||||||
0x37 |
lstore |
将栈顶long型数值存入指定的局部变量 |
||||||||||||
0x38 |
fstore |
将栈顶float型数值存入指定的局部变量 |
||||||||||||
0x39 |
dstore |
将栈顶double型数值存入指定的局部变量 |
||||||||||||
0x3A |
astore |
指令格式: astore index
功能描述: 将栈顶数值(objectref)存入当前 frame的局部变量数组中指定下标 (index)处的变量中,栈顶数值出栈。
index : 无符号一byte整数。该指令和wide联 用,index可以为无符号两byte整数。
|
||||||||||||
|
||||||||||||||
0x3B |
istore_0 |
将栈顶int型数值存入第一个局部变量 |
||||||||||||
0x3C |
istore_1 |
将栈顶int型数值存入第二个局部变量 |
||||||||||||
0x3D |
istore_2 |
将栈顶int型数值存入第三个局部变量 |
||||||||||||
0x3E |
istore_3 |
将栈顶int型数值存入第四个局部变量 |
||||||||||||