JVM(1)-運行時數據區 I.運行時五大數據區 II.對象的創建(HotSpot) IV.對象的訪問

一直沒有系統的學習JVM相關的知識,之前偶爾查看某些章節,比如類的加載過程、GC策略、內存模型等,趁這段時間全面系統學習一番,記錄下關鍵的知識點方便後面翻閱。

I.運行時五大數據區

  1. 方法區(Method Area)
  2. 虛擬機棧(Java Virtual Machine Stack)
  3. 本地方法區(Native Method Area)
  4. 堆(Heap)
  5. 程序計數器(Program counter Register)
  • 程序計數器
    線程私有,若執行的是java方法,則記錄的是當前正在執行的虛擬機字節碼指令地址;若執行的是本地方法,這個計數器爲空(Undefined)。此內存區域是在Java虛擬機規範中唯一沒有指定OutOfMemoryError的區域。

  • 虛擬機棧
    線程私有,描述的是方法執行的模型,當執行一個方法時會創建一個棧幀(Stack Frame)用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息,生命週期與線程相同。每一個方法的執行的完整過程,就對應着一個棧幀在虛擬機棧中的進棧出棧。
    此區域有兩個異常:當棧深度超過虛擬機的規定時,StackOverFlowError;當擴展時無法申請到足夠的內存,OutOfMemeryError。

  • 本地方法棧
    與虛擬機棧的區別是,虛擬機棧是爲執行Java方法服務,而本地方法棧是爲執行Native方法服務,同樣這個區域也會拋出StackOverFlowError、OutOfMemeryError。


  • 線程共享,但也有線程私有的分配緩存TLAB(Thread Local Allocation Buffer),幾乎所有的對象、數組都在這個內存區域分配,這個區域也稱爲GC堆(Garbage Collected Head),不是叫垃圾堆。可分爲新生代,老年代,再進一步細分可分爲Eden、From Survivor、ToSurvivor。當堆中沒有足夠的內存完成實例分配且無法擴展時,拋出OutOfMemoryError。

  • 方法區
    線程共享,用於存儲虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。當方法區無法滿足內存分配需求時,將拋出OutOfMemoryError。
    此區域包含常量池、

II.對象的創建(HotSpot)

通過new關鍵字創建(或克隆、反序列化)

  1. 首先檢查這個指令的參數是否能在常量池中定位到一個類的符號引用,並檢查這個符號引用所代表的類是否被加載、解析和初始化過,如果沒有則必須先完成類的加載過程;
  2. 分配內存,類加載完成後,對象的大小已經確定;分配過程需要考慮同步問題,採用CAS加失敗重試;或者採用本地線程分配緩存(TLAB),這種方式只有在TLAB用完的時候才需要同步;
  3. 內存分配完成後,就進行零值初始化(不包含對象頭),如果是採用TLAB那這個過程也可以提前至TLAB的過程;
  4. 執行<init>來進行初始化;

III.對象內存佈局

對象頭(Header)
實例數據(Instance Data)
對齊填充(Padding)非必須

其中對齊填充不是非必須的,主要是HotSpot VM的自動內存管理系統要求對象的起始地址必須是8字節的整數倍。

IV.對象的訪問

方式一:採用對象句柄,通過 Java虛擬機棧本地變量表->對象句柄(在堆中劃分一個句柄池)->實例數據或者對象類型數據;這種方式在實例對象地址改變時(比如GC後整理內存空間),棧中引用的句柄的地址不需要改變;


方式二:直接引用,棧中的引用存儲的是對象的地址,這種情況就需要堆中的對象佈局必須考慮如何放置對象類型的相關信息,這種方式就少了一次尋址,速度更快。Sun HotSpot虛擬機就是採用這種方式。


下一篇:垃圾收集器與內存分配策略

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