作者:王智通
一、 前言
ajvm是筆者正在開發中的一個java虛拟機, 想通過編寫這個jvm幫助程式員了解jvm的具體實作細節, 它是國内第一個開源的java虛拟機項目:https://github.com/cloudsec/ajvm, 同時筆者把它的開發筆記也分享到了ata上。 在前面4篇筆記中, 已經實作了class檔案加載器, 反彙編器,jvm的crash資訊處理, 同時它已經能運作簡單的java代碼了。 在今天的這篇筆記中, 将開始分享ajvm的記憶體管理子產品是如何編寫的。
二、記憶體配置設定
看下面一段java代碼:
首先用javac編譯下, 然後用ajvm的反彙編器檢視bytecode:
源碼中data = new int[2];對應的彙編指令為:
根據jvm虛拟機規範的描述, newarray指令的作用是, 從操作數堆棧用取出data數組的元素個數,然後根據newarray後面的type進行計算要申請的記憶體大小, type的值在虛拟機規範中如下:
是以10代表這個int類型的數組, 接下來就要給data這個數組從heap中配置設定記憶體了。
ajvm的記憶體堆用的是slab算法, slab的記憶體結構如下:
源碼中的slab.c是它完整的實作, 不熟悉slab的同學請自行google。
三、垃圾回收
gc是java程式員普遍關心的問題, 當記憶體不夠時, 将會觸發jvm的垃圾回收機制。
ajvm使用最原始的引用計數法, 需要建立一個新的資料結構:
當數組申請完記憶體後, 将會建立一個新的jvm_object與其對應, ref_count被初始化為0, addr指向數組的首位址, size表示數組的大小, jvm_object将會被加入到jvm_obj_list_head連結清單中, 在這将來的垃圾回收時将會用到。
當數組被引用時, 我們跟數組的位址在jvm_object連結清單中找到它, 并且把ref_count加1, 表示這個數組在被引用。 比如上面的:
這條指令就會對data數組進行引用, 我們隻要在iastore的解釋代碼裡, 對data對應的ref_count加1即可:
對于數組data1, 同樣進行了記憶體配置設定, 但是始終沒有被引用到, 是以data1将會是gc回收時要釋放的對象。
這是ajvm最簡單的gc算法了, 後續将會對其進行優化。
四、示範執行
下面是ajvm對上述java代碼的解釋和執行過程: