一個Java對象在堆上除了成員信息,還有其餘內容嗎?他在堆上是如何佈局的?接下來本文將以Hotspot爲例分析Java對象內存佈局之謎。算法
在Hotspot中一個Java對象包含以下三個部分:數組
對象頭要分兩種類型:數據結構
不一樣類型JVM下,對象頭每一部分佔用內存大小jvm
數據類型 | 32位JVM(bit) | 64位JVM(bit) | 開啓指針壓縮的64位JVM(bit) |
---|---|---|---|
Mark Word | 32 | 64 | 64 |
Klass Pointer | 32 | 64 | 32 |
Array Length | 32 | 32 | 32 |
可見在64位JVM中開啓指針壓縮(-XX:UseCompressedOops)後, JVM只是針對類型指針(Klass Pointer)進行壓縮。而數組長度無論在什麼類型的JVM裏都是32bit。ide
不一樣類型JVM下,對象頭佔用內存大小佈局
數據類型 | 32位JVM(bit) | 64位JVM(bit) | 開啓指針壓縮的64位JVM(bit) |
---|---|---|---|
普通對象 | 64 | 128 | 96 |
數組對象 | 96 | 160 | 128 |
因而可知,對象頭仍是比較耗空間的。那麼用了這麼多內存,對象頭具體都存放了寫什麼信息呢?線程
mark word裏存放的是對象運行時的信息,不一樣狀態的對象裏mark word 存放的信息是不一樣的。具體內容可看下錶:設計
32位JVM指針
存儲內容(30bit) | 鎖狀態(2bit) |
---|---|
identify_hashcode:25 | age:4 | biased_lock:1 | (01)無鎖 |
threadId:23 | age:4 | epoch:2 | biased_lock:1 | (01)偏向鎖 |
ptr_to_lock_record:30 | (00)輕量級鎖 |
ptr_to_heavyweight_monitor:30 | (10)重量級鎖 |
gc_info:30 | (11)GC標記 |
64位JVMcode
存儲內容(62bit) | 鎖狀態(2bit) |
---|---|
unused:25 | identify_hashcode:25 | unused:1 | age:4 | biased_lock:1 | (01)無鎖 |
threadId:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | (01)偏向鎖 |
ptr_to_lock_record:62 | (00)輕量級鎖 |
ptr_to_heavyweight_monitor:62 | (10)重量級鎖 |
gc_info:62 | (11)GC標記 |
名詞解釋:
爲何要這麼實現?
identify_hashcode 既然有方法能夠生成爲何要放在對象頭裏?
當對象的狀態不是默認狀態時,對象的hashcode去哪兒了?
類型指針存放的是該對象對應的類的指針。即該指針應該指向方法區的內存區域。
數組長度只在數組類型的對象中存在。用於記錄數組的長度。避免獲取數組長度時,動態計算。以空間換時間。
該部分存儲了一個類定義的全部的數據類型信息,包含從父類中繼承的信息。
因爲HotSpot規定對象的大小必須是8的整數倍,而對象頭恰好是8的整數倍,若是對象實例數據這部分不是的話,就須要佔位符對齊填充。