1. 程式人生 > >java虛擬機器(第二版) 第二章總結 (二)

java虛擬機器(第二版) 第二章總結 (二)

本文總結下java虛擬機器的第二章的第三小節

 

1、(原文2.3)HotSpot虛擬機器物件探祕

 

文中以HotSpot虛擬機器為例,講述了java物件的建立以及訪問。

 

當我們寫的new關鍵字被虛擬機器執行時:

 <1>、檢查new所對應的引數是否能在常量池中定位到一個類的符號引用;

<2>、檢查這個符號引用代表的類是否已被載入、 解析和初始化過; 

<3>、如果沒有, 那必須先執行相應的類載入過程(書中第7章);

<4>、上述步驟執行結束後,則為新生物件分配記憶體,有兩種方式

      <1、指標碰撞:指堆記憶體為規整的,可以簡單的分為已被佔用的和未被佔用的兩塊,中間以一個指標作為分隔,為新物件分配記憶體只是將指標向未被佔用的記憶體空間移動下而已;

      <2、空閒列表:指堆記憶體並非規整的,虛擬機器維護著一個未使用記憶體塊的列表,當新建物件時,從列表中查詢一個可以容下新物件的記憶體即可;

選擇哪種分配方式由使用哪種垃圾收集器決定,Serial、 ParNew等帶Compact(標記-整理演算法)過程的收集器時, 系統採用的分配演算法是指標碰撞,

CMS,基於Mark-Sweep演算法(標記-清除演算法)的收集器時, 通常採用空閒列表。

 

注:關於各個垃圾收集器所採用的演算法概述如下,後續會詳細總結

    Serial:複製演算法(新生代)

    Serial Old:標記-整理演算法(老年代)

    ParNew:(Serial的多執行緒版本)複製演算法(新生代)

    Parallel Scavenge:(“吞吐量優先”收集器)複製演算法(新生代)

    Parallel Old:(Parallel Scavenge的老年代版本)標記-整理演算法 (老年          代)

CMS和G1後續會詳細總結。

 

繼續物件的建立內容總結...

 

<5>、解決物件建立在多執行緒情況下的執行緒安全問題的兩種方案:

    <1、CAS配上失敗重試的方式保證更新操作的原子性;

    <2、把記憶體分配的動作按照執行緒劃分在不同的空間之中進行, 即每個執行緒在Java堆中預先分配一小塊記憶體, 稱為本地執行緒分配緩衝( Thread Local Allocation Buffer,TLAB) 。 哪個執行緒要分配記憶體, 就在哪個執行緒的TLAB上分配, 只有TLAB用完並分配新的TLAB時, 才需要同步鎖定;

    虛擬機器通過-XX: +/-UseTLAB引數設定使用TLAB。

<6>、初始化預設值;

<7>、對物件進行必要的設定, 例如這個物件是哪個類的例項、 如何才能找到類的元資料資訊、 物件的雜湊碼、 物件的GC分代年齡等資訊;

2、(原文2.3.2)在HotSpot虛擬機器中, 物件在記憶體中的佈局分為3塊區域: 物件頭( Header) 、例項資料( Instance Data) 和對齊填充( Padding) 。此部分都是些硬知識,且不常見,故暫時未總結,感興趣的讀者可以閱讀原書。

 

3、(原文2.3.3) 物件的訪問定位

 

主流的訪問方式有使用控制代碼和直接指標兩種


 <1>使用控制代碼:此種情況Java堆中會分出一塊記憶體作為控制代碼池, 引用中儲存的就是物件的控制代碼地址, 而控制代碼中包含了物件例項資料與型別資料各自的具體地址資訊,好處是控制代碼地址穩定,頻繁的垃圾收集下只改例項資料指標,而引用本身不變。

<2>直接指標:看圖我就不說話了

 

好處是速度更快, 節省了一次指標定位的時間開銷,且因物件訪問在Java中超級頻繁, 所以會節省一大筆時間;

 

HotSpot是使用直接指標來訪問物件的

 

本節完。

本文暫時總結了java虛擬機器(第二版)中的2.3節的主要知識點,和一些up主自己的知識點,如果有記憶差錯,還望見諒,後面我會找時間繼續的,最後,我總結的知識點比較簡練,如果需要了解詳細內容的話,請閱讀原書。也歡迎大家關注我的公眾號號 “up隨想”,關注後或許會收到up主的小福利哦!!