通過代碼計算對象的大小
先說結論:默認16個字節
工具JOL :Java Object Layout java對象布局
引入POM文件
<dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.10</version> </dependency>
public class HelloJol { public static void main(String[] args) { Object o = new Object(); String s = ClassLayout.parseInstance(o).toPrintable(); System.out.println(s); } }
打印結果
前兩行就是markWord 固定8個字節
分析java對象的組成
普通對象
對象頭:markword 8 (鎖的標識位:標識對象的狀態,GC標記:對象被回收了多少次 分代年齡)
ClassPointer指針:-XX:+UseCompressedClassPointers 為4字節(默認開啟) 不開啟為8字節 (對象屬於哪個Class)
實例數據 引用類型:-XX:+UseCompressedOops 為4字節(默認開啟) 不開啟為8字節 Oops Ordinary Object Pointers(成員變量的引用 比如下面的Object o)
Padding對齊,8的倍數 (64位的機器 按塊來讀,一下子讀16個字節)
觀察虛擬機配置命令 java -XX:+PrintCommandLineFlags -version
數組對象
對象頭:markword 8
ClassPointer指針同上
數組長度:4字節
數組數據
對齊 8的倍數
用例測試
public class T03_SizeOfAnObject { public static void main(String[] args) { System.out.println(ObjectSizeAgent.sizeOf(new Object())); System.out.println(ObjectSizeAgent.sizeOf(new int[] {})); System.out.println(ObjectSizeAgent.sizeOf(new P())); } //一個Object占多少個字節 // -XX:+UseCompressedClassPointers -XX:+UseCompressedOops // Oops = ordinary object pointers private static class P { //8 _markword //4 _class pointer int id; //4 String name; //4 int age; //4 byte b1; //1 byte b2; //1 Object o; //4 byte b3; //1 } }
打印結果:
16 = 對象頭8個 + ClassPointer指針 4個 +padding對齊 4個
16 = 對象頭8個 + ClassPointer指針 4個 +數組長度 4個 +padding對齊0個
32 = 對象頭8個 + ClassPointer指針 4個 + int id 4個 + name的引用四個 + int age 4個+1+1+4+1 + padding對齊
對象頭具體包括什么
8個字節64位 看對象的狀態分配64位。普通狀態和鎖定狀態每一位完全不一樣
主要包括
鎖的標識位:標識對象的狀態,
GC標記:對象被回收了多少次 分代年齡
當一個對象已經計算過identity hash code它就無法進入偏向鎖狀態
對象是怎么定位的
T t = new T()
t是怎么找到堆內存中的T對象
1.句柄池:
2.直接指針(HotSpot的實現):