一、 Bytecode instructions
1. 组成
由opcode和arguments两部分组成。
opcode:一个unsigned byte值,标示某条特定的指令;
arguments:定义某条指令的行为,紧跟在opcode后面;
Instruction arguments和Instruction operands:
arguments编译期可见,存储在已编译文件中;
operand来自operand堆栈,仅在运运行期可见。
类型描述符(Type descriptors).png
方法描述符(Method descriptors).png
2. Bytecode instructions分类:
2.1 在local variables 和 operand stack之间转移数据的指令
- xLOAD:从local variable中读取压入operand stack中;
- ILOAD: boolean, byte, char, short, or int;
- LLOAD: long
- FLOAD: float
- DLOAD: double
- ALOAD: 非primitive类型,如object和references。
2.2. 仅操作operand stack的指令
- Stack: POP, DUP, SWAP
-
Constants: 压入一个常量数据到operand stack中;
ACONST_NULL:压入null
ICONST_0:压入0
FCONST_0 :压入0f
DCONST_0 :压入0d
BIPUSH b :压入byte类型b;
SIPUSH s:压入short类型 s;
LDC cst: 压入任意的int, float, long, double, String, Class类型cst; - Arithmetic and logic :
- Casts:
- Objects:
- Fields:
- Methods:
- Arrays:
- Jumps:
- Return:
举例:
package pkg;
public class Bean {
private int f;
public int getF() {
return this.f;
}
public void setF(int f) {
this.f = f;
}
}
getF()方法的指令:
ALOAD 0 //读取local variable 0(this指针)压入operand stack中;
GETFIELD pkg/Bean f I //弹出栈顶元素,并将this.f压入operand stack,
IRETURN //弹出栈顶元素,并把它返回给调用者;
setF()方法的指令:
ALOAD 0 //将local variable 0 (this指针) 压入operand stack中;
ILOAD 1 // 将local variable 1(参数f)压入到operand stack中;
PUTFIELD pkg/Bean f I // 弹出上面两个,将f保存到this.f中
RETURN // 返回至调用者。
默认构造方法:
Bean() {
super();
}
对应的字节指令:
ALOAD 0 //读取local variable 0(this指针),并压入operand stack中;
INVOKESPECIAL java/lang/Object <init> ()V // 从operand stack中弹出栈顶元素, 调用Object的<init>方法;
RETURN //返回至调用者
新的setter方法:
public void checkAndSetF(int f) {
if (f >= 0) {
this.f = f;
} else {
throw new IllegalArgumentException();
}
}
对应的字节码指令:
ILOAD 1 //读取local variable 1(参数f),压入operand stack中
IFLT label //弹出栈顶元素、且与0比较,如果Less Than(LT)0,跳转至label标签; 否则的话继续执行下一条指令;
ALOAD 0 //读取local variable 0(this指针),压入operand stack中;
ILOAD 1 //读取local variable 1(参数f),压入operand stack中;
PUTFIELD pkg/Bean f I //弹出上面两个,将参数f保存到this.f中;
GOTO end //无条件跳转至end标签
label:
NEW java/lang/IllegalArgumentException //创建一个Exception对象并压入operand堆栈
DUP //复制operand堆栈的栈顶元素;
INVOKESPECIAL java/lang/IllegalArgumentException <init> ()V //弹出栈顶
元素并调用Exception的构造方法;
ATHROW //弹出栈顶元素(另外一个副本),作为异常抛出
end:
RETURN //返回至调用者
方法:
public static void sleep(long d) {
try {
Thread.sleep(d);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
对应的bytecode指令: