JVM學習之物件記憶體佈局,物件頭
本篇內容來自《深入理解Java虛擬機器_JVM高階特性與最佳實踐》,感謝作者。
建立物件之後需要使用物件,java中除了對物件屬性方法的呼叫以外還有加鎖實現同步等其他操作,這裡的鎖加在了哪裡,如何記錄鎖,如何對鎖進行分類(有物件鎖,class鎖),垃圾回收機制中有關於GC的標記,知道當前物件分代的年齡,這些都需要我們去探尋物件具體的記憶體佈局。
1 物件的記憶體佈局
HotSpot虛擬機器中物件儲存分成三塊區域,物件頭(Header),例項資料(Instance Data),對齊填充(Padding)。
物件頭:物件頭記錄物件的資訊,包括雜湊碼,GC分代年齡,鎖狀態標誌,執行緒持有的鎖,偏向時間戳,型別指標。
例項資料:儲存物件自身定義的資料
對齊填充:為了對齊填充的額外資料。
2 物件頭
從上面物件各個區域儲存的資訊可以看到物件頭儲存了物件的主要描述資訊。
物件頭分成兩部分:
(1)Mark Work 儲存物件執行時資料
雜湊碼,GC分代年齡,鎖狀態標誌,執行緒持有的鎖,偏向執行緒ID,偏向時間戳等,這部分長度在32和64位虛擬機器中分貝佔32bit和64bit。物件頭記錄了與物件自身定義的資料無關的額外儲存成本,所以Mark Word被設計成非固定的資料結構以便在極小的儲存空間儲存儘量更多的資訊。
物件頭標誌位對應:
物件雜湊碼、物件分代年齡 標誌位 01 未被鎖定
指向鎖記錄的指標 標誌位 00 輕量級鎖定
指向重量級鎖的指標 標誌位 10 重量級鎖定
空,不需要記錄資訊 標誌位 11 GC標記
偏向執行緒id,偏向時間戳,物件分代年齡 標誌位 01 可偏向
(2)物件的型別指標
Type Point物件指向它的類元資料的指標,虛擬機器通過這個指標來確定這個物件是哪個類的例項。並不是所喲肚餓虛擬機器實現都必須在物件資料上白哦劉類這陣。如果物件是一個java陣列,那在物件頭中還必須有一塊用於記錄陣列長度的資料,因為虛擬機器可以通過普通物件的原資料資訊確定java物件大小,但是從陣列元素的原資料中無法確定陣列的大小。
從物件頭的Mark Word中可以知道,GC垃圾收集器和鎖的資訊都是儲存在物件頭中的,所以可以方便的對物件進行操作。
3例項資料&對齊填充
例項資料物件真正儲存的有效資訊,也是在程式程式碼中所定義的各種型別的欄位內容。
對齊填充並不是必然存在的,僅僅起著佔位符的作用,保證物件頭部分正好是8位元組的倍數。