JVM學習筆記16 字節碼執行

bilibili-JVM學習筆記16
The Java Virtual Machine Specification - Java SE 8 Edition

JVM學習筆記11 - Java字節碼初識
JVM學習筆記12 - 解讀筆記11中的attributes
JVM學習筆記13
JVM學習筆記14 異常
JVM學習筆記15 方法執行

編譯執行 解釋執行

  • 現代 JVM 在執行 Java 代碼的時候,通常都會將解釋執行與編譯執行二者結合起來進行;
    • 解釋執行
      • 通過 jvm 解釋器來讀取字節碼,遇到相應的字節碼指令就去執行該指令;
    • 編譯執行
      • 通過即時編譯器(Just In Time, JIT)將字節碼指令轉換爲本地機器碼來執行;現代 JVM 會根據代碼熱點來生成相應的本地機器碼;
      • 失去了可移植性的優點
      • 提高了執行效率
  • 基於棧的指令集與基於寄存器的指令集之間的關係
    • JVM 執行字節碼指令所採取的方式是基於棧的指令集
      • 主要操作有入棧和出棧;
      • 優點:可以在不同平臺之間移植
      • 缺點:完成相同的操作,指令數量通常比基於寄存器的指令集數量要多;在內存中完成執行指令的操作,速度慢很多;
      • 雖然虛擬機可以採用一些優化手段,但總體來說,基於棧的指令集的執行還是要慢一些的;
    • 基於寄存器的指令集
      • 與硬件架構緊密關聯,無法做到可移植;
      • 基於寄存器的指令集是直接由 CPU 來執行的,它是在高速緩衝區中進行執行的,速度比在內存中執行高出一個數量級;

JVM執行棧指令集實例剖析

java 源碼

package new_package.jvm.p55;

public class MyTest {

    public int cal() {
        int a = 6;
        int b = 1;
        int c = 5;
        int d = 3;
        int result = (a + b - c) * d;
        return result;
    }

    public static void main(String[] args) {
        System.out.println(new MyTest().cal());
    }
}

javap -v new_package.jvm.p55.MyTest

cal 方法相關的字節碼

 public int cal();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=6, args_size=1
         0: bipush        6
         2: istore_1
         3: iconst_1
         4: istore_2
         5: iconst_5
         6: istore_3
         7: iconst_3
         8: istore        4
        10: iload_1
        11: iload_2
        12: iadd
        13: iload_3
        14: isub
        15: iload         4
        17: imul
        18: istore        5
        20: iload         5
        22: ireturn
      LineNumberTable:
        line 6: 0
        line 7: 3
        line 8: 5
        line 9: 7
        line 10: 10
        line 11: 20
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      23     0  this   Lnew_package/jvm/p55/MyTest;
            3      20     1     a   I
            5      18     2     b   I
            7      16     3     c   I
           10      13     4     d   I
           20       3     5 result   I

解析:

  1. stack=2 表示當前方法的操作數棧最大深度爲 2
  2. locals=6 表示當前方法局部變量表長度爲 6
  3. args_size=1 表示當前方法入參數量爲 1 ;(實例方法的第一個隱形入參 this ,指向當前實例)

接下來對字節碼指令逐個解釋:

  1. bipush 6

bipush :將一個 int 類型的數值壓入操作數棧

此處是將數值 6 壓入操作數棧

在這裏插入圖片描述
2. istore_1

istore_1 : istore 1 的簡寫;
將操作數棧頂的 int 類型數值從操作數棧中彈出,放到局部變量表的索引爲 1 的位置處

在這裏插入圖片描述

  1. iconst_1

iconst_1 : bipush 1 的簡寫

此處是將數值 1 壓入操作數棧

在這裏插入圖片描述

  1. istore_2

將操作數棧頂的 int 類型數值從操作數棧中彈出,放到局部變量表的索引爲 2 的位置處

在這裏插入圖片描述

  1. iconst_5

此處是將數值 5 壓入操作數棧

在這裏插入圖片描述

  1. istore_3

將操作數棧頂的 int 類型數值從操作數棧中彈出,放到局部變量表的索引爲 3 的位置處

在這裏插入圖片描述

  1. iconst_3

此處是將數值 3 壓入操作數棧

在這裏插入圖片描述

  1. istore 4

將操作數棧頂的 int 類型數值從操作數棧中彈出,放到局部變量表的索引爲 4 的位置處

在這裏插入圖片描述

  1. iload_1

iload_1 : iload 1 的簡寫

iload 從局部變量中加載一個 int 類型的值

iload_1 即從索引 1 的位置加載一個值,壓入操作數棧

在這裏插入圖片描述

  1. iload_2

iload_2 即從索引 2 的位置加載一個值,壓入操作數棧

在這裏插入圖片描述

  1. iadd

從操作數棧中彈出兩個值(int 類型的值),然後相加,將結果壓入操作數棧

在這裏插入圖片描述

  1. iload_3

從索引 3 的位置加載一個值,壓入操作數棧

在這裏插入圖片描述

  1. isub

從操作數棧中彈出兩個數(int 類型),第一個爲減數,第二個爲被減數,結果爲被減數 - 減數,將結果重新壓入操作數棧;

在這裏插入圖片描述

  1. iload 4

從索引 4 的位置加載一個值,壓入操作數棧

在這裏插入圖片描述

  1. imul

兩個 int 類型的值相乘,並將結果重新壓入操作數棧;

在這裏插入圖片描述

  1. istore 5

將操作數棧頂的 int 類型數值從操作數棧中彈出,放到局部變量表的索引爲 5 的位置處

在這裏插入圖片描述

  1. iload 5

從索引 5 的位置加載一個值,壓入操作數棧

在這裏插入圖片描述

  1. ireturn

從當前幀的操作數棧中彈出值,並將其壓入調用者的幀操作數棧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章