[开源JVM] yvm - 自制Java虚拟机
中文 | English
| | |
YVM是用C++寫的一個Java虛擬機,現在支持Java大部分功能,以及一個基于標記清除算法的并發垃圾回收器. 不過還有很多bug等待修復。
感興趣的朋友pull request/fork/star吧。
Github repo
https://github.com/racaljk/yvm
已支持語言特性
高級特性逐步支持中,可以開Issue提議或者直接PR
- Java基本算術運算,流程控制語句,面向對象。
- RTTI
- 字符串拼接(+,+=符號重載)
- 異常處理(可輸出stacktrace)
- 創建異步線程
- Synchronized(支持對象鎖)
- 垃圾回收(標記清除算法)
構建和運行
- 先決條件
- Boost(>=1.65) 請在CMakeLists.txt中手動配置Boost庫位置
- CMake(>=3.5)
- C++14
- gcc/msvc/mingw均可
- 老生常談
運行效果
- helloworld
- 快速排序
- and more see its github repository readme.md...
開發文檔
1. 從字節碼到對象
MethodArea負責管理字節碼到JavaClass的完整生命周期。MethodArea的方法是自解釋的:
class MethodArea { public:// 方法區需要從運行時目錄中搜索相關的*.class文件MethodArea(const vector<string>& libPaths);~MethodArea();// 查看一個類是否存在JavaClass* findJavaClass(const string& jcName);//加載jcName類bool loadJavaClass(const string& jcName);//移除jcName(該方法用于垃圾回收器)bool removeJavaClass(const string& jcName);//鏈接jcName類,初始化static字段void linkJavaClass(const string& jcName);//初始化jcName,初始化靜態字段,調用static{}void initJavaClass(CodeExecution& exec, const string& jcName);public://輔助方法,如果不存在jcName則加載 JavaClass* loadClassIfAbsent(const string& jcName);//如果未鏈接jcName則鏈接void linkClassIfAbsent(const string& jcName);//如果未初始化jcName則初始化void initClassIfAbsent(CodeExecution& exec, const string& jcName); }假設磁盤存在一個Test.class文件,它會經歷如下過程:
Test.class[磁盤中]-> loadJavaClass("Test.class")[內存中] -> linkJavaClass("Test.class")->initJavaClass("Test.class")
現在虛擬機就可以使用這個JavaClass創建對應的對象了:
// yrt 是全局運行時對象,ma表示方法區模塊,jheap表示堆模塊 JavaClass* testClass = yrt.ma->findJavaClass("Test.class"); JObject* testInstance = yrt.jheap->createObject(*testClass);2.1 對象內部構造
虛擬機執行時棧上存放的都是JObject,它的結構如下:
struct JObject {std::size_t offset = 0; const JavaClass* jc{}; };offset唯一代表一個對象,所有在堆上面的操作都需要這個offset。jc指向對象的Class表示。
堆中的對象是按照<offset,fields>方式進行存放的:
只要我們持有offset,就可以查找/添加/刪除對應的field
數組幾乎和上面類似,只是多了長度,少了Class指針
struct JArray {int length = 0;std::size_t offset = 0; }; [1] -> <3, [field_a, field_b, field_c]> [2] -> <0, []> [3] -> <2, [field_a,field_b]> [4] -> <1, [field_a]> [..] -> <..,[...]>2.2 從對象創建到消亡
上面提到,對象持有一個offset和jc,其中jc表示的JavaClass是由MethodArea負責管理的,offset則是由JavaHeap負責管理。JavaHeap提供了大量API,這里選取的是最重要的:
class JavaHeap { public://創建對象和數組JObject* createObject(const JavaClass& javaClass);JArray* createObjectArray(const JavaClass& jc, int length);//獲取對象字段auto getFieldByName(const JavaClass* jc, const string& name,const string& descriptor, JObject* object);//設置對象字段void putFieldByName(const JavaClass* jc, const string& name,const string& descriptor, JObject* object,JType* value);//設置數組元素void putElement(const JArray& array, size_t index, JType* value);//獲取數組元素auto getElement(const JArray& array, size_t index);//移除對象和數組void removeArray(size_t offset;void removeObject(size_t offset); };還是Test.class那個例子,假設對應的Test.java構造如下:
public class Test{public int k;private String hello; }在第一步我們已經獲取到了Test類在虛擬機中的類表示以及對象表示,現在就可以對類的字段進行操作了:
const JavaClass* testClass = yrt.ma->findJavaClass("Test.class"); JObject* testInstance = yrt.jheap->createObject(*testClass); //獲取hello字段 JObject* helloField = yrt.jheap->getFieldByName(testClass,"hello","Ljava/lang/String;",testInstance); //設置k字段 yrt.jheap->putFieldByName(testClass,"k","I",testInstance);Ⅰ. 關于JDK
部分JDK類是JVM運行攸關的,但由于JDK比較復雜不便于初期開發,所以這里用重寫過的JDK代替,源碼參見javaclass目錄,可以使用compilejava.bat進行編譯,編譯后*.class文件位于bytecode.
目前重寫過的JDK類有:
- java.lang.String
- java.lang.StringBuilder
- java.lang.Throwable
- java.lang.Math(::random())
- java.lang.Runnable
- java.lang.Thread
Wiki和源碼中有很多詳細的開發文檔,如果想探索關于YVM的更多內容,請移步瀏覽.
License
所有代碼基于MIT協議
轉載于:https://www.cnblogs.com/ysherlock/p/8688454.html
總結
以上是生活随笔為你收集整理的[开源JVM] yvm - 自制Java虚拟机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 主席树学习小结(POJ 2104)
- 下一篇: Java集合之TreeMap源码解析上篇