這段時間一直在看JVM相關的書籍,雖然有點難,至少到目前爲止尚未放棄。寫這篇文章的目的:當作本身這段時間學習的小回顧。本章主要經過幾個代碼片斷,分析下局部變量表與操做數棧之間的數據傳遞關係,重點講解iload
,istore
,iconst_<n>
,iadd
命令java
局部變量表:每一個棧幀內部都包含一組稱爲局部變量表的變量列表學習
操做數棧:每一個棧幀內部都包含一個操做數棧this
iconst_0:把int型的0值壓入操做數棧code
iload:將一個局部變量加載到操做數棧上索引
istore:將一個數值從操做數棧上存儲到局部變量表中編譯
iadd:返回棧頂的兩個元素作加法運算,並加結果壓棧class
首先經過dos進入TestApp.class所在的目錄,而後運行命令javap -c TestApp
,便可看到編譯後的字節碼文件test
如下是一個java源代碼變量
public void test1(){ int c=0; }
編譯後的字節碼書籍
public void test1(); Code: 0: iconst_0 1: istore_1 2: return
代碼分析
由於test1()
是一個實例方法,因此在局部變量表中,索引爲0的位置會保存該方法所在類的引用(this),因此纔會出現istore_1
而不是istore_0
。
咱們對int c = 0
作下拆解,一個常量0,一個變量c。
0: iconst_0 //將常量0壓入操做數棧 1: istore_1 //將棧頂出棧,即c=0 2: return //由於是void,沒有返回值
Java源代碼以下
public static void test2(){ int c=0; }
編譯後的字節碼文件
public static void test2(); Code: 0: iconst_0 1: istore_0 2: return
分析
由於test2()
是一個靜態的方法,不會在局部變量表中插入任何數據。因此你看到的是istore_0
而不是像程序片斷一
中的istore_1
。其餘分析跟程序片斷一
相同
java源代碼
public int test3(){ int c=0; return c; }
編譯後的字節碼
public int test3(); Code: 0: iconst_0 1: istore_1 2: iload_1 3: ireturn
分析
0: iconst_0 //將常量0壓棧 1: istore_1 //將棧頂出棧,及c=0 2: iload_1 //將變量c壓入棧頂 3: ireturn //返回棧定元素
Java源代碼
public int test4(int a,int b){ int c=0; return a+b; }
編譯後的字節碼
public int test4(int, int); Code: 0: iconst_0 1: istore_3 2: iload_1 3: iload_2 4: iadd 5: ireturn
** 分析
由於test4(int a,int b)
是實例方法,因此在局部變量表
索引爲0的位置會插入this
。
由於test4(int a,int b)
帶有兩個參數,因此在局部變量索引
索引爲1的位置插入a,在索引爲2的位置插入b。
0: iconst_0 //將常量0壓棧 1: istore_3 //將棧頂出棧,即c=0,將c存儲到局部變量表索引爲3的位置 2: iload_1 //將局部變量表中索引爲1的變量壓棧,即a壓棧 3: iload_2 //將局部變量表中索引爲2的變量壓棧,即b壓棧 4: iadd //將棧頂兩個元素出棧,作加法,而後把結果再入棧(即a,b出棧,將a+b入棧) 5: ireturn //返回a+b的值
java源代碼
public int test5(int a,int b){ int c=0; c= a+b; return c; }
編譯後的字節碼
public int test5(int, int); Code: 0: iconst_0 1: istore_3 2: iload_1 3: iload_2 4: iadd 5: istore_3 6: iload_3 7: ireturn
分析
0: iconst_0 //將常量0壓棧 1: istore_3 //將棧頂出棧,及c=0 2: iload_1 //從局部變量表中加載索引爲1的變量壓棧,即a壓棧 3: iload_2 //從局部變量表中加載索引爲2的變量壓棧,即b壓棧 4: iadd //將棧頂兩個元素出棧,作加法,而後將結果壓棧,及a+b壓棧 5: istore_3 //將棧頂元素出棧,並保存到局部變量表中,即c=a+b 6: iload_3 //從局部變量表中加載索引爲3的變量壓棧,即c壓棧 7: ireturn //返回棧頂元素,即返回c