字节码指令
下面会指令族的概念,先说明一下
前缀x取值 |
含义 |
i |
int |
b |
byte |
c |
char |
s |
short |
l |
long |
f |
float |
d |
double |
a |
对象引用 |
这里没有boolean类型的,他的操作指令同int,以如下代码为例
Java Code
1 |
|
package com.test.a; |
常量入操作数栈
const系列
用于将特定的常量压入操作数栈,常量就包含在指令中,如
iconst_1、iconst_2、iconst_3将int 1、2、3压入操作数栈中,iconst_m1将-1压入操作数栈
lconst_0将long 0压入操作数栈
dconst_0将double 0压入操作数栈
aconst_null将null压入操作数栈
以如下代码为例
Java Code
1 |
|
package com.test.b; |
push系列
bipush接收8位整数作为参数,sipush接收16位整数作为参数,将参数压入栈中
以如下代码为例
Java Code
1 |
|
package com.test.c; |
ldc
ldc接收一个参数,该参数指向常量池中的int、float、String等的索引,将指定的元素压入操作数栈
ldc2_w接收一个参数,该参数指向常量池中的long、double等的索引
以如下代码为例
Java Code
1 |
|
package com.test.d; |
出栈赋值局部变量表
store系列
istore_1从操作数栈中弹出一个int,将它赋值给局部变量表中的第1个局部变量,istore_2从操作数栈中弹出一个int赋值给第2个局部变量
lstore_1从操作数栈中弹出一个long赋值给第1个局部变量
xstore接收一个位置参数,从操作数栈中弹出一个数据,将其赋值给指定位置的局部变量
以如下代码为例
Java Code
1 |
|
package com.test.e; |
注意后面的istore 4,istore 5,其位置参数指的是局部变量表的槽位
局部变量入操作数栈
load系列
iload_0、fload_0表示将第0个局部变量压入操作数栈(只不过局部变量表中的数据类型不同)
aload_0表示将第0个局部变量压入操作数栈,第0个局部变量为对象引用
xload接收一个位置参数,将指定位置的局部变量压入操作数栈
以如下代码为例
Java Code
1 |
|
package com.test.f; |
对象操作
创建
指令new用于创建对象,其接收一个参数,指向常量池中的类名的索引,执行完成后将新创建对象的引用压入操作数栈
以如下代码为例
Java Code
1 |
|
package com.test.g; |
字段访问
putfield用于设置实例对象的字段,要求此时操作数栈的栈顶为要设置的数据,次栈顶为要设置的对象的引用,接收一个参数为要设置的字段的名称
操作完成以后弹出栈顶、次栈顶
getfield用于获取实例对象的字段,要求此时操作数栈的栈顶为要获取的对象的引用,接收一个参数为要获取的字段的名称
操作完成以后弹出栈顶,将获取到的数据压入操作数栈
以如下代码为例
Java Code
1 |
|
package com.test.h; |
putstatic、getstatic用于访问类字段
以如下代码为例
Java Code
1 |
|
package com.test.i; |
函数调用
函数调用都是通过invoke指令进行的
invokespecial:调用一些特殊的方法如构造函数、私有方法、父类的方法,这些方法都是静态绑定的
invokestatic:调用静态方法,也是静态绑定的
invokevirtual:调用对象的实例方法,会根据对象的实际类型进行派发,支持动态调用,是最常用的调用方式
invokeinterface:调用接口的方法,也支持动态调用
以invokevirtual为例,操作时要求操作数栈的栈顶为参数,次栈顶为要操作的对象,参数为要调用的方法的名称
操作完成以后弹出栈顶元素,将结果压入操作数栈
以如下代码为例
Java Code
1 |
|
package com.test.j; |
数组
使用newarray创建基本类型的数组,使用anewarray创建对象类型的数组
使用xastore给数组项赋值,操作时要求操作数栈的栈顶依次为值、索引、数组引用,操作完成会弹出栈顶元素
使用xaload获取数组项,操作时要求操作数栈的栈顶为索引、数组引用,操作完成会弹出栈顶元素,并将数组项压入操作数栈。
以如下代码为例
Java Code
1 |
|
package com.test.k; |
dup、pop
dup意为duplicate复制,他会将栈顶元素复制一份并再次压入操作数栈
pop则将栈顶元素弹出操作数栈
以如下代码为例
Java Code
1 |
|
package com.test.l; |
new指令完成以后,栈顶只有一份对象引用
但是后续对给对象连续进行两次操作,一次通过invokespecial调用构造函数,一次通过astore将栈顶元素赋值给局部变量
这两个操作都会将栈顶元素弹出,故为了连续两次使用相同的栈顶元素,使用dup指令复制了一份对象引用
return
当函数要返回时,需要将返回值压入到调用者的操作数栈,此时需要使用xreturn指令
当返回值为void时,使用return指令,当返回值为int时,使用ireturn指令
运算
比较控制