天天看點

HotSpot虛拟機對象的建立、記憶體布局、通路定位

注:本文為閱讀《深入了解Java虛拟機 JVM進階特性與最佳實戰》第2版(周志明)一書後的學習筆記,摘抄自書中的内容,特此說明。

1、對象的建立

虛拟機遇到一條new指令時,首先将去檢查這個指令的參數是否能在常量池中定位到一個類的符号引用,并且檢查這個符号引用代表的類是否已被加載、解析和初始化過。如果沒有,那必須先執行相應的類加載過程,本書第7章将探讨這部分内容的細節。

在類加載檢查通過後,接下來虛拟機将為新生對象配置設定記憶體。對象所需記憶體的大小在類加載完成後便可完全确定(如何确定将在2.3.2節中介紹),為對象配置設定空間的任務等同于把一塊确定大小的記憶體從Java堆中劃分出來。

記憶體配置設定的2種方式:

(選擇哪種配置設定方式由Java堆是否規整決定,而Java堆是否規整又由所采用的垃圾收集器是否帶有壓縮整理功能決定)

  • 指針碰撞(Bump the Pointer)

    Java堆中記憶體是絕對規整的,所有用過的記憶體都放在一邊,空閑的記憶體放在另一邊,中間放着一個指針作為分界點的訓示器,那所配置設定記憶體就僅僅是把那個指針向空閑空間那邊挪動一段與對象大小相等的距離。

  • 空閑清單(Free List)

    Java堆中的記憶體并不是規整的,已使用的記憶體和空閑的記憶體互相交錯,那就沒有辦法簡單地進行指針碰撞了,虛拟機就必須維護一個清單,記錄上哪些記憶體塊是可用的,在配置設定的時候從清單中找到一塊足夠大的空間劃分給對象執行個體,并更新清單上的記錄。

記憶體配置設定完成後,虛拟機需要将配置設定到的記憶體空間都初始化為零值(不包括對象頭),這一步操作保證了對象的執行個體字段在Java代碼中可以不賦初始值就直接使用,程式能通路到這些字段的資料類型所對應的零值。

接下來,虛拟機要對對象進行必要的設定,例如這個對象是哪個類的執行個體、如何才能找到類的中繼資料資訊、對象的哈希碼、對象的GC分代年齡等資訊。這些資訊存放在對象的對象頭(Object Header)之中。

2、對象的記憶體布局

在HotSpot虛拟機中,對象在記憶體中存儲的布局可以分為3塊區域:對象頭(Header)、執行個體資料(Instance Data)和對齊填充(Padding)。

HotSpot虛拟機的對象頭包括兩部分資訊:

  • Mark Word

    第一部分用于存儲對象自身的運作時資料,如哈希碼(HashCode)、GC分代年齡、鎖狀态标志、線程持有的鎖、偏向線程ID、偏向時間戳等,這部分資料的長度在32位和64位的虛拟機(未開啟壓縮指針)中分别為32bit和64bit。

  • 類型指針

    對象頭的另外一部分是類型指針,即對象指向它的類中繼資料的指針,虛拟機通過這個指針來确定這個對象是哪個類的執行個體。并不是所有的虛拟機實作都必須在對象資料上保留類型指針,換句話說,查找對象的中繼資料資訊并不一定要經過對象本身,這點将在2.3.3節讨論。

接下來的執行個體資料部分是對象真正存儲的有效資訊,也是在程式代碼中所定義的各種類型的字段内容。無論是從父類繼承下來的,還是在子類中定義的,都需要記錄起來。這部分的存儲順序會受到虛拟機配置設定政策參數(FieldsAllocationStyle)和字段在Java源碼中定義順序的影響。

對齊填充并不是必然存在的,也沒有特别的含義,它僅僅起着占位符的作用。

3、對象的通路定位

建立對象是為了使用對象,我們的Java程式需要通過棧上的reference資料來操作堆上的具體對象。

目前主流的通路方式有使用句柄和直接指針兩種:

  • 如果使用句柄通路的話,那麼Java堆中将會劃分出一塊記憶體來作為句柄池,reference中

    存儲的就是對象的句柄位址,而句柄中包含了對象執行個體資料與類型資料各自的具體位址信

    息。

    HotSpot虛拟機對象的建立、記憶體布局、通路定位
  • 如果使用直接指針通路,那麼Java堆對象的布局中就必須考慮如何放置通路類型資料的

    相關資訊,而reference中存儲的直接就是對象位址。

    HotSpot虛拟機對象的建立、記憶體布局、通路定位

兩種通路方式的對比,這兩種對象通路方式各有優勢:

使用句柄來通路的最大好處就是reference中存儲的是穩定的句柄位址,在對象被移動(垃圾收集時移動對象是非常普遍的行為)時隻會改變句柄中的執行個體資料指針,而reference本身不需要修改。

使用直接指針通路方式的最大好處就是速度更快,它節省了一次指針定位的時間開銷,由于對象的通路在Java中非常頻繁,是以這類開銷積少成多後也是一項非常可觀的執行成本。Sun HotSpot虛拟機是使用第二種方式進行對象虛拟機通路的。