这一篇其实是对前面一篇《JVM字节码执行模型及字节码指令集》的一个延续和举例。结合例子看一下条件判定和无条件跳转指令对虚拟机栈的数据操作。
?
??? 我们先来看一段代码例子。这里addEspresso()添加浓度方法会判断参数,如果参数<=1那么久抛出异常。
package bytecode; /** * * Created by yunshen.ljy on 2015/6/21. */ public class CaramelMacchiato { private int espresso ; public void addEspresso(int espresso) { if (espresso > 1) { this.espresso = espresso; } else { throw new IllegalArgumentException(); } } }
?然后看一下addEspresso方法的字节码如下:
0: iload_1 1: iconst_1 2: if_icmple 13 5: aload_0 6: iload_1 7: putfield #2; //Field espresso:I 10: goto 21 13: new #3; //class java/lang/IllegalArgumentException 16: dup 17: invokespecial #4; //Method java/lang/IllegalArgumentException."<init>":()V 20: athrow 21: return
??这里我们来对字节码指令进行解析。
??? 第一行和第二行指令分别是把参数espresso以及常量1 从局部变量表压入操作数栈。
??? 第三行指令,也就是条件语句的比较指令,比较操作数栈顶,第一条第二条指令对应的值的大小,如果不满足比较条件,就会跳转到字节码的13 这个位置。也即是进入到异常处理。
??? 第四行指令到第六行指令就是我们前面一篇介绍过的,如同setBean 方法一样的。对于field的赋值操作。
??? 第五行 goto 指令,无条件跳转到所制定的21的位置,方法返回,清空方法栈。
??? 第六行开始是异常处理。这里先是new 指令创建一个Exception对象,并且将其压入操作数栈。
??? 第七行指令复制刚才的对象,并且压入操作数栈。
??? 第八行是将其中一个Exception对象出栈,病调用其构造器方法。
??? 第九行将另外一个对象出栈,并且抛出异常,所以也是清空、结束了当前的方法栈。
原文:http://lijingyao8206.iteye.com/blog/2221144