物件的記憶體佈局
在HotSpot虛擬機器中,物件在記憶體中儲存的佈局可以分為3塊區域:物件頭(Header)、例項資料(Instance Data)和對齊填充(Padding)。
HotSpot虛擬機器的物件頭包括兩部分資訊,第一部分用於儲存物件自身的執行時資料,如雜湊碼(HashCode)、GC分代年齡、鎖狀態標誌、執行緒持有的鎖、偏向執行緒ID、偏向時間戳等,這部分資料的長度在32位和64位的虛擬機器(未開啟壓縮指標)中分別為32bit和64bit,官方稱它為“Mark Word”。物件需要儲存的執行時資料很多,其實已經超出了32位、64位Bitmap結構所能記錄的限度,但是物件頭資訊是與物件自身定義的資料無關的額外儲存成本,考慮到虛擬機器的空間效率,Mark Word被設計成一個非固定的資料結構以便在極小的空間記憶體儲儘量多的資訊,它會根據物件的狀態複用自己的儲存空間。例如,在32位的HotSpot虛擬機器中,如果物件處於未被鎖定的狀態下,那麼Mark Word的32bit空間中的25bit用於儲存物件雜湊碼,4bit用於儲存物件分代年齡,2bit用於儲存鎖標誌位,1bit固定為0,而在其他狀態(輕量級鎖定、重量級鎖定、GC標記、可偏向)下物件的儲存內容見表2-1。
表2-1 HotSpot虛擬機器物件頭Mark Word
儲存內容 標 志 位 狀 態
物件雜湊碼、物件分代年齡 01 未鎖定
指向鎖記錄的指標 00 輕量級鎖定
指向重量級鎖的指標 10 膨脹(重量級鎖定)
空,不需要記錄資訊 11 GC標記
偏向執行緒ID、偏向時間戳、物件分代年齡 01 可偏向
物件頭的另外一部分是型別指標,即物件指向它的類後設資料的指標,虛擬機器通過這個指標來確定這個物件是哪個類的例項。並不是所有的虛擬機器實現都必須在物件資料上保留型別指標,換句話說,查詢物件的後設資料資訊並不一定要經過物件本身,這點將在2.3.3節討論。另外,如果物件是一個Java陣列,那在物件頭中還必須有一塊用於記錄陣列長度的資料,因為虛擬機器可以通過普通Java物件的後設資料資訊確定Java物件的大小,但是從陣列的後設資料中卻無法確定陣列的大小。
程式碼清單2-2為HotSpot虛擬機器markOop.cpp中的程式碼(註釋)片段,它描述了32bit下Mark Word的儲存狀態。
程式碼清單2-2 markOop.cpp片段
// Bit-format of an object header (most significant first, big endian layout below):
// 32 bits:
// --------
// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
// size:32 ------------------------------------------>| (CMS free block)
// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
接下來的例項資料部分是物件真正儲存的有效資訊,也是在程式程式碼中所定義的各種型別的欄位內容。無論是從父類繼承下來的,還是在子類中定義的,都需要記錄起來。這部分的儲存順序會受到虛擬機器分配策略引數(FieldsAllocationStyle)和欄位在Java原始碼中定義順序的影響。HotSpot虛擬機器預設的分配策略為longs/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Pointers),從分配策略中可以看出,相同寬度的欄位總是被分配到一起。在滿足這個前提條件的情況下,在父類中定義的變數會出現在子類之前。如果CompactFields引數值為true(預設為true),那麼子類之中較窄的變數也可能會插入到父類變數的空隙之中。
第三部分對齊填充並不是必然存在的,也沒有特別的含義,它僅僅起著佔位符的作用。由於HotSpot VM的自動記憶體管理系統要求物件起始地址必須是8位元組的整數倍,換句話說,就是物件的大小必須是8位元組的整數倍。而物件頭部分正好是8位元組的倍數(1倍或者2倍),因此,當物件例項資料部分沒有對齊時,就需要通過對齊填充來補全。
相關文章
- JVM -- 物件的記憶體佈局JVM物件記憶體
- Java物件的記憶體佈局Java物件記憶體
- .NET物件的記憶體佈局物件記憶體
- Java物件記憶體佈局Java物件記憶體
- OC物件記憶體佈局物件記憶體
- 物件記憶體佈局 (7)物件記憶體
- C++ 物件的記憶體佈局C++物件記憶體
- JVM-物件及物件記憶體佈局JVM物件記憶體
- 【記憶體管理】記憶體佈局記憶體
- 圖文詳解Java物件記憶體佈局Java物件記憶體
- C++ 虛繼承 物件記憶體佈局C++繼承物件記憶體
- 圖說C++物件模型:物件記憶體佈局詳解C++物件模型記憶體
- [CPP] 類的記憶體佈局記憶體
- 物件的例項化、記憶體佈局以及訪問定位物件記憶體
- JVM中java例項物件在記憶體中的佈局JVMJava物件記憶體
- C程式記憶體佈局C程式記憶體
- c程式的記憶體佈局圖C程式記憶體
- 深入理解 Python 的物件複製和記憶體佈局Python物件記憶體
- JVM之物件的建立、記憶體佈局、訪問走位總結JVM物件記憶體
- Object o = new Object()佔多少個位元組?-物件的記憶體佈局Object物件記憶體
- 深度解讀《深度探索C++物件模型》之C++物件的記憶體佈局C++物件模型記憶體
- Rust 程式設計:記憶體佈局Rust程式設計記憶體
- 10-記憶體空間佈局記憶體
- [譯]Go語言記憶體佈局Go記憶體
- 分散載入與記憶體佈局記憶體
- 【JVM之記憶體與垃圾回收篇】物件例項化記憶體佈局與訪問定位JVM記憶體物件
- 虛擬函式的記憶體佈局(上)函式記憶體
- C++ 繼承中的記憶體佈局C++繼承記憶體
- 深入理解Java虛擬機器之物件的記憶體佈局、訪問定位Java虛擬機物件記憶體
- Java虛擬機器14:Java物件大小、物件記憶體佈局及鎖狀態變化Java虛擬機物件記憶體
- C 語言結構體記憶體佈局問題結構體記憶體
- C語言結構體記憶體佈局問題C語言結構體記憶體
- Solidity語言學習筆記————41、記憶體佈局Solid筆記記憶體
- [轉帖]重磅硬核|一文聊透物件在JVM中的記憶體佈局等(一)物件JVM記憶體
- 99.9%的Java程式設計師都說不清的問題:JVM中的物件記憶體佈局?Java程式設計師JVM物件記憶體
- iOS記憶體管理佈局及管理方案-理論篇iOS記憶體
- 一個由程式記憶體佈局異常引起的問題記憶體
- 重磅硬核 | 一文聊透物件在 JVM 中的記憶體佈局,以及記憶體對齊和壓縮指標的原理及應用物件JVM記憶體指標