1. 程式人生 > >【Java虛擬機器】3、虛擬機器物件

【Java虛擬機器】3、虛擬機器物件

--------------------------------【Java虛擬機器】系列--------------------------------
1、Java技術體系
2、Java記憶體區域
3、虛擬機器物件
4、OutOfMemoryError異常
--------------------------------【Java虛擬機器】系列--------------------------------

Part II: 自動記憶體管理機制

第2章 Java記憶體區域與記憶體溢位異常

HotSpot虛擬機器物件探祕

更進一步瞭解虛擬機器記憶體中資料的其他細節,譬如它們是如何建立、如何佈局以及如何訪問的。實用優先,以常用的虛擬機器HotSpot和常用的記憶體區域Java堆為例,深入探討HotSpot虛擬機器在Java堆中物件分配、佈局和訪問的全過程。

物件的建立

當虛擬機器遇到一條含有new的指令時,會進行一系列物件建立的操作:

  1. 檢查該指令的引數是否能在常量池中定位到一個類的符號引用,並且檢查這個符號引用代表的類是否已被載入、解析和初始化過;
    • 若常量池中沒有這個類的符號引用,說明這個類還沒有被定義!丟擲ClassNotFoundException;
    • 若常量池中有這個類的符號引用,則進行下一步工作;
  2. 虛擬機器為新生物件分配記憶體,物件所需記憶體大小在類載入完成後便完全確定,根據Java堆中的記憶體是否規整分兩種分配方式:
  • 指標碰撞(Bump the Pointer):如果JVM的垃圾收集器採用複製演算法或標記-整理演算法,那麼堆中空閒記憶體是完整的區域,並且空閒記憶體和已使用記憶體之間有一個指標標記。那麼當為一個物件分配記憶體時,只需把那個指標向空閒空間那邊挪動一段與物件大小相等的距離。

    • 空閒列表(Free List): 如果JVM的垃圾收集器採用標記-清除演算法,那麼堆中空閒區域和已使用區域交錯,因此需要用一張“空閒列表”來記錄堆中哪些區域是空閒區域,從而在建立物件的時候根據這張“空閒列表”找到空閒區域,並分配記憶體。

    綜上所述:JVM究竟採用哪種記憶體分配方法,取決於它使用了何種垃圾收集器。

  1. 另外一個需要考慮的併發下的執行緒安全問題,有兩種方案:
    • 分配記憶體空間的動作進行同步處理—實際上虛擬機器採用CAS配上失敗重試的方式保證更新操作的原子性;
    • 為每個執行緒分配一小塊記憶體(稱為本地執行緒分配緩衝,TLAB),各個執行緒獨立分配,只有TLAB用完需要分配新的才需要同步鎖定,虛擬機器通過-XX:+/-UseTLAB引數來設定;
  2. 虛擬機器將分配到的記憶體空間都初始化為零值(不包括物件頭);這保證了物件的例項欄位在Java程式碼中可以不賦初始值就直接使用,程式能訪問這些欄位的資料型別所對應的零值;
  3. 虛擬機器設定物件的物件頭資訊,包含物件是哪個類的例項,如何找到類的元資料資訊、物件的hash碼、物件的GC分代年齡等;
  4. 執行new指令後會接著執行 < init>方法,把物件按照程式設計師的意願進行初始化,這樣一個真正可用的物件才算完全產生出來;

總結過程:類載入分配記憶體初始化物件設定物件

物件的記憶體佈局

物件在記憶體中儲存的佈局可以分為3塊區域:物件頭(Header)、例項資料(Instance Data)和對齊填充(Padding)。 -

  • 物件頭
    1. 用於儲存物件本身的執行時資料,如雜湊碼(HashCode)、GC分代年齡、鎖狀態標誌、執行緒持有的鎖、偏向執行緒ID、偏向時間戳等;
    2. 型別指標,即物件指向它的類元資料的指標,虛擬機器通過這個指標來確定這個物件是哪個類的例項。此外,如果物件是一個數組,那麼物件頭中還要包含陣列長度。
  • 例項資料
    例項資料部分是物件真正儲存的有效資訊,也是在程式程式碼中所定義的各種型別的欄位內容,它的儲存順序會受到虛擬機器分配策略和欄位在Java原始碼中定義順序的影響;
  • 對齊填充
    對齊填充並不是必然存在的,也沒有特殊含義,它僅僅起著佔位符的作用。
物件的訪問定位

物件訪問方式取決於虛擬機器實現而定,目前主流的訪問方式有使用控制代碼直接指標兩種。

  • 控制代碼訪問方式
    Java堆中將會劃分出一塊記憶體來作為控制代碼池,reference中儲存的就是物件的控制代碼地址,而控制代碼中包含了物件例項資料與型別資料各自的具體地址資訊;
    控制代碼訪問

  • 直接指標訪問方式
    reference中儲存的直接就是物件地址;
    直接指標
    兩種物件訪問方式的比較:

  • 控制代碼訪問的好處是reference中儲存的是穩定的控制代碼地址,在物件被移動時只會改變控制代碼中的例項資料指標,而reference本身不需要修改;

  • 使用直接指標的好處是速度更快,減少了時間開銷。Sun HotSpot使用的就是直接指標方式訪問的。