if eq = 153,// 0x99 当栈顶int型数值value=0 时跳转
if ne = 154,// 0x9a 当栈顶int型数值value!=0 时跳转
if lt = 155,// 0x9b 当栈顶int型数值value<0 时跳转
if ge = 156,// 0x9c 当栈顶int型数值value>=0 时跳转
if gt = 157,// 0x9d 当栈顶int型数值value>0时跳转
if le = 158,// 0x9e 当栈顶int型数值value<=0 时跳转
if_icmp eq = 159,// 0x9f valu1=value2时结果为真,为真跳转
if_icmp ne = 160,// 0xa0 valu1!=value2时结果为真,为真跳转
if_icmp lt = 161,// 0xa1 value1<value2时结果为真,为真跳转
if_icmp ge = 162,// 0xa2 valu1>=value2时结果为真,为真跳转
if_icmp gt = 163,// 0xa3 valu1>value2时结果为真,为真跳转
if_icmp le = 164,// 0xa4 valu1<=value2时结果为真,为真跳转
if_acmpeq = 165,// 0xa5 比较栈顶两引用型数值,当结果相等时跳转
if_acmpne = 166,// 0xa6 比较栈顶两引用型数值,当结果不相等时跳转
if_acmp_null = 198, // 0xc6 为null时跳转
if_acmp_nonnull = 199,// 0xc7 不为null时跳转
goto_ = 167,// 0xa7 无条件跳转
jsr = 168,// 0xa8 跳转至指定16位offset位置,并将jsr下一条指令地址压入栈顶
/** All conditional jumps come in pairs. To streamline the
* treatment of jumps, we also introduce a negation of an
* unconditional jump. That opcode happens to be jsr.
*/
// 就是与无条件的跳转goto成对存储的,jsr表示有条件的跳转
int dontgoto = jsr;
如上的一些指令有一点规律:
(1)相对应的一对指令的编码是相邻的,如ifeq和ifne的编码是153和154
(2)较小的指令编码是奇数,例如153
只有一个例外就是ifnull和ifnonnull编码分别是198和199,不满足第二个条件
还有另外一些复合指令,如xcmp与ifxx的组合,例子如下:
public void test(boolean result){
final double a = 1;
final double b = 2;
if(a>=b){
System.out.println("xxx");
}
}
要进行常量折叠,最终生成的class内容如下:
public void test(boolean);
flags: ACC_PUBLIC
Code:
stack=2, locals=6, args_size=2
0: dconst_1
1: dstore_2
2: ldc2_w #2 // double 2.0d
5: dstore 4
7: return
更改如上的指令,去掉final关键字,如下:
public void test(boolean result){
double a = 1;
double b = 2;
if(a>=b){
System.out.println("xxx");
}
}
class文件内容如下:
public void test(boolean);
flags: ACC_PUBLIC
Code:
stack=4, locals=6, args_size=2
0: dconst_1
1: dstore_2
2: ldc2_w #2 // double 2.0d
5: dstore 4
7: dload_2
8: dload 4
10: dcmpl
11: iflt 22
14: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
17: ldc #5 // String xxx
19: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: return