JOL全稱為Java Object Layout江醇,是分析JVM中對象布局的工具硼啤,該工具大量使用了Unsafe父丰、JVMTI來解碼布局情況,所以分析結(jié)果是比較精準的纺铭,接下來我們就具體操作下。
我們先創(chuàng)建幾個待分析的類對象實例刀疙。
public class A {}
public class B {
private long s;
}
public class C {
private int a;
private long s;
}
int[] aa = new int[0];
然后創(chuàng)建分析主函數(shù):
public class Test {
public static void main(String[] args) {
A a = new A();
System.out.println(ClassLayout.parseInstance(a).toPrintable());
B b = new B();
System.out.println(ClassLayout.parseInstance(b).toPrintable());
C c = new C();
System.out.println(ClassLayout.parseInstance(c).toPrintable());
int[] aa = new int[0];
System.out.println(ClassLayout.parseInstance(aa).toPrintable());
}
}
1.運行壞境為64位虛擬機舶赔。
2.主函數(shù)里所用到的包為jol工具,引入方式如下谦秧。
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
輸出結(jié)果如下:
結(jié)果如上圖所示竟纳,A對象為16bytes,B對象為24bytes疚鲤,C對象為24bytes锥累,數(shù)組對象為16bytes。
接下來我們具體分析下這四個對象集歇,看jol分析的結(jié)果是否正確桶略。
java對象的組成部分:
- 1.對象頭
在jvm虛擬機中每一個java對象都有一個對象頭,對象頭中包含標記字段以及對象指針,標記字段用來儲存hash碼际歼、gc信息以及鎖信息惶翻,而指針則指向改對象的類。在64位jvm虛擬機中這兩部分都是64位的鹅心,所以也就是需要128位大新来帧(16 bytes)。
注意:64位虛擬機中在堆內(nèi)存小于32GB的情況下旭愧,UseCompressedOops是默認開啟的颅筋,該參數(shù)表示開啟指針壓縮,會將原來64位的指針壓縮為32位榕茧。 - 2.實例數(shù)據(jù)
類中所有的實例字段數(shù)據(jù)垃沦。 - 3.內(nèi)存填充部分(alignment)
該部分作用是用來保證java對象在虛擬機中占內(nèi)存大小為8N bytes。 - 4.數(shù)組長度
這個是數(shù)組對象才特有的用押。
java的基礎數(shù)據(jù)類型所占內(nèi)存情況如下表格:
boolean | byte | short | char | int | long | float | double |
---|---|---|---|---|---|---|---|
1 bytes | 1 bytes | 2 bytes | 2 bytes | 4 bytes | 8 bytes | 4 bytes | 8 bytes |
A對象:A對象就是一個空對象肢簿,所以在內(nèi)存中占據(jù)大小就是對象頭的大小等于16 bytes,由于開啟指針壓縮則對象頭占據(jù)大小為12 bytes蜻拨,但是12 bytes字節(jié)不是8的倍數(shù)所以需要進行內(nèi)存對齊池充,最后加上了4 bytes的空白字節(jié),最終該對象占據(jù)16 bytes大小缎讼。
B對象:B對象包含一個long基本數(shù)據(jù)類型收夸,所以大小等于 12 bytes+8 bytes=20 bytes,20 bytes不是8N所以需要加上4 bytes的填充字節(jié)血崭,最終該對象占據(jù)24 bytes卧惜。
C對象:C對象包含一個long、一個int基本數(shù)據(jù)類型夹纫,所以大小等于 12 bytes+8 bytes+4 bytes=24 bytes咽瓷,正好8N,不需要內(nèi)存填充舰讹,最終該對象占據(jù)24 bytes茅姜。
D對象:D對象是一個數(shù)組對象,因為數(shù)組對象會多一個數(shù)組長度存儲部分月匣,所以大小等于12 bytes+4 bytes=16 bytes钻洒,注意這里數(shù)組長度我給的是0,如果給的是1大家可以試試看輸出結(jié)果又是多少呢锄开。
至此我們已經(jīng)分析完畢素标,感興趣的小伙伴可以去試一下,加深下對對象內(nèi)存大小的理解萍悴,或者更改下虛擬機的運行參數(shù)UseCompressedOops 設置為-XX:-UseCompressedOops關(guān)閉指針壓縮看看結(jié)果又是多少糯钙。
參考: