在前面的文章介紹了對象在虛拟機中的建立過程。本文主要是記錄下對象在虛拟機中的記憶體布局配置設定情況。
JVM的記憶體對象介紹[建立和通路]
對象的記憶體布局
在HotSpot虛拟機中,對象在記憶體中存儲的布局可以分為3塊區域:對象頭,執行個體資料和對齊填充。
序号 | 區域 | 說明 |
1 | 對象頭 | 存儲對象的hashCode或鎖的相關資訊 |
2 | 執行個體資料 | 存儲對象執行個體相關的資料 |
3 | 對齊填充 | 占位符的作用 |
1.對象頭
對象頭包含兩部分
第一部分内容
第一部分存儲自身的運作時資料,如hashCode,GC分代年齡,鎖狀态标志,線程持有的鎖,偏向線程ID,偏向時間戳,對象分代年齡,這部分資訊稱為"Mark Word",Mark Word 被設計成一個非固定的資料結構以便在極小的空間記憶體儲盡量多的資訊,它會根據自己的狀态複用自己的存儲空間。32位或者64位存儲也有差別。
例如:在 32 位的 HotSpot 虛拟機中,如果對象處于未被鎖定的狀态下,那麼 Mark Word 的 32bit 空間中的 25bit 用于存儲對象哈希碼,4bit 用于存儲對象分代年齡,2bit 用于存儲鎖标志位,1bit 固定為 0,如下表所示
鎖狀态 | 25bit | 4bit | 1bit是否是偏向鎖 | 2bit鎖标志位 |
無鎖狀态 | 對象的hashCode | 對象的分代年齡 | 01 |
對象在其他狀态下(輕量級鎖定,重量級鎖定,GC标記,可偏向)對象的存儲内容如下:
存儲内容 | 标志位 | 狀态 |
對象哈希碼,對象分代年齡 | 01 | 未鎖定 |
指向鎖記錄的指針 | 00 | 輕量級鎖定 |
指向重量級鎖的指針 | 10 | 膨脹(重量級鎖定) |
空,不需要記錄資訊 | 11 | GC标記 |
偏向線程ID,偏向時間戳, 對象分代年齡 | 01 | 可偏向 |
第二部分内容
第二部分存儲類型的指針,既對象執行它的類中繼資料的執行(方法區),虛拟機通過這個指針來确定這個對象是那個類的執行個體。如果對象是一個Java數組,在對象頭中還須有一塊用于記錄數組長度的資料,因為虛拟機可通過普通Java對象的中繼資料資訊确定Java對象的大小,但從數組的中繼資料中無法确定數組的大小。
2.執行個體資料(Instance Data)
執行個體資料部分是對象真正存儲的有效資訊,也是在程式代碼中所定義的各種類型的字段内容。這部分的存儲順序會受到虛拟機配置設定政策參數(FieldsAllocationStyle)和字段在 Java 源碼中定義順序的影響。
3.對齊填充(Padding)
對齊填充不是必然存在的,沒有特别的含義,它僅起到占位符的作用。
由于 HotSpot VM 的自動記憶體管理系統要求對象起始位址必須是 8 位元組的整數倍,也就是說對象的大小必須是 8 位元組的整數倍。對象頭部分是 8 位元組的倍數,是以當對象執行個體資料部分沒有對齊時,就需要通過對齊填充來補全。
對象大小估算
Class A {
int i;
byte b;
String str;
}