天天看點

JVM 位元組碼指令對于棧幀資料操作舉例

這一篇其實是對前面一篇《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 指令,無條件跳轉到位元組碼參數所指定的十二行return指令的位置,方法傳回,清空方法棧。

    第八行開始是異常處理。這裡先是new 指令建立一個Exception對象,并且将其壓入操作數棧。

    第九行指令複制剛才的對象,并且壓入操作數棧。

    第十行是将其中一個Exception對象出棧,并調用其構造器方法。

    第十一行将另外一個對象出棧,并且抛出異常,是以也是清空、結束了目前的方法棧。