用 Java 實現一個簡單的虛擬機 ?

Learning By Doing.java

最近開了個新坑, 目的是用 Java 8 實現一個簡單的解釋型 JVM. 目前零零散散提交了 100 多 commits. 最終的目標是 自舉.
目前進度大概 60%, 基本的 ClassFile 解析, 類加載, 字節碼執行, 方法調用, 對象實例化, 多態, 接口基本可用.git

0x00 背景

mini-jvm 項目的動機.github

  1. 這有點意思.
  2. 我的平常工做中主要使用 Java, 須要對 JVM 有必定的理解, 然而 Hotspot 源碼實在是看不下去.
  3. Learning By Doing.

寫此文的目的.bash

  1. 稍加記錄, 以備往後回顧,
  2. 廣而告之, 以期對 JVM 感興趣的同窗能瞭解到有這麼一個項目.
  3. 尋道友, 但願感興趣的同窗能夠聯繫我, 以期繼續完善這個項目.

0x01

在實現的過程當中, 已力保代碼簡單, 可讀, 可測. 目前爲止代碼 5000 行出頭, 竊覺得, 對於想了解 JVM 基本原理的同窗是個不錯的入門項目. 在此基礎上, 爲了便於理解一些概念, 好比基於棧的虛擬機實現原理, 會特地實現一個邊緣特性用來快速理解.數據結構

0x02 基於棧的虛擬機基本實現.

對 JVM 字節碼執行引擎稍有了解的話, 應該對棧幀有所瞭解jvm

棧幀(Stack Frame)是用於支持虛擬機進行方法調用和方法執行的數據結構 棧幀隨着方法調用而建立,隨着方法結束而銷燬,棧幀的存儲空間分配在 Java 虛擬機棧中,每一個棧幀擁有本身的局部變量表(Local Variables)操做數棧(Operand Stack)ui

若是嘗試用過 javap -v classfile , method 區塊亦有所體現.spa

下面看一個簡單的例子3d

public class Hello {
  public static int return1() {
    return 1;
  }
}
複製代碼

編譯並使用code

cat <<EOF > Hello.java
public class Hello {
  public static int return1() {
    return 1;
  }
}
EOF
# 很明顯, 若是 return1 方法被調用, 返回結果必定是 1 .
javac Hello.java
javap -v Hello.class
複製代碼

輸出較長, 只摘抄方法部分以下

public static int return1();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: iconst_1
         1: ireturn
複製代碼

stack=1 即此方法棧操做數棧大小爲 1 locals=0 即此方法局部變量表大小爲 0 args_size 即此方法參數個數爲 0

0: iconst_1
1: ireturn
複製代碼

這便是該方法的字節碼
0: iconst_1 , 表示該方法指令集 0 位置 的指令爲 iconst_1 , iconst_1 的含義是 將 int 值 1 push 到操做數棧.
1: ireturn , 表示該方法指令集 1 位置 的指令爲 ireturn , ireturn 的含義是, 將當前操做數棧棧頂 int 類型值彈出, 而且把當前棧幀彈出, 並將從操做數棧彈出的 int 類型值 push 到當前棧幀的操做數棧.

相似 iconst_1 這種指令, JVM 規範定義了 200 + 個.

爲了方便理解. 項目實現了一個簡單的類彙編語言來描述字節碼,並解釋執行.

return1 1 0 0 
0 iconst_1
1 ireturn
複製代碼

對比上方 javap -v 的輸出, 去除了一些冗餘信息.
下爲實際截圖

1574438006.png

稍複雜一點的 sum10

1574438135.png

更復雜一點的 sumN

1574438239.png

0x03 尾聲

簡介到此告一段落, 更多信息可往 github repo 瞭解.
如有興趣參與, 務必聯繫我, 虛左以待.

聯繫方式
vx: echo "Z3V4aW5na2VfCg==" | base64 -d
mail: echo "YWRtaW5AZ3V4aW5na2UuY29tCg==" | base64 -d

項目地址
github: github.com/guxingke/mi…

相關文章
相關標籤/搜索