1. 程式人生 > 其它 >《深入理解 Java 虛擬機器》閱讀筆記2系列:基於棧的位元組碼解釋執行引擎

《深入理解 Java 虛擬機器》閱讀筆記2系列:基於棧的位元組碼解釋執行引擎

技術標籤:Javajavajvm

基於棧的位元組碼解釋執行引擎

這個棧,就是棧幀中的運算元棧。

解釋執行

先通過 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(); } }