《深入理解 Java 虛擬機器》閱讀筆記2系列:基於棧的位元組碼解釋執行引擎
阿新 • • 發佈:2021-01-17
基於棧的位元組碼解釋執行引擎
這個棧,就是棧幀中的運算元棧。
解釋執行
先通過 javac 將程式碼編譯成位元組碼,虛擬機器再通過載入位元組碼檔案,解釋執行位元組碼檔案生成機器碼,解釋執行的流程如下:
詞法分析 -> 語法分析 -> 形成抽象語法樹 -> 遍歷語法樹生成線性位元組碼指令流
指令集分類
基於棧的指令集
-
優點:
- 可移植:暫存器由硬體直接提供,程式如果直接依賴這些硬體暫存器,會不可避免的受到硬體的約束;
- 程式碼更緊湊:位元組碼中每個位元組對應一條指令,多地址指令集中還需要存放參數;
- 編譯器實現更簡單:不需要考慮空間分配問題,所需的空間都在棧上操作。
-
缺點: 執行速度稍慢
- 完成相同的功能,需要更多的指令,因為出入棧本身就產生相當多的指令;
- 頻繁的棧訪問導致頻繁的記憶體訪問,對於處理器而言,記憶體是執行速度的瓶頸。
-
示例: 兩數相加
iconst_1 // 把常量1入棧 iconst_1 iadd // 把棧頂兩元素出棧相加,結果入棧 istore_0 // 把棧頂值存入第0個Slot中
基於暫存器的指令集
示例: 兩數相加
mov eax, 1
add eax, 1
執行過程分析
public class Architecture {
/*
calc函式的位元組碼分析:
public int calc();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1 // stack=2,說明需要深度為2的運算元棧
// locals=4,說明需要4個Slot的區域性變量表
0: bipush 100 // 將單位元組的整型常數值push到運算元棧
2: istore_1 // 將運算元棧頂的整型值出棧並存放到第一個區域性變數Slot中
3: sipush 200
6: istore_2
7: sipush 300
10: istore_3
11: iload_1 // 將區域性變量表第一個Slot中的整型值複製到運算元棧頂
12: iload_2
13: iadd // 將運算元棧中頭兩個元素出棧並相加,將結果重新入棧
14: iload_3
15: imul // 將運算元棧中頭兩個元素出棧並相乘,將結果重新入棧
16: ireturn // 返回指令,結束方法執行,將運算元棧頂的整型值返回給此方法的呼叫者
*/
public int calc() {
int a = 100;
int b = 200;
int c = 300;
return (a + b) * c;
}
public static void main(String[] args) {
Architecture architecture = new Architecture();
architecture.calc();
}
}