首先說明爲什麼要學習java的對象佈局?
當對一個代碼塊加鎖的時候,剛學習java的時候認爲是鎖的代碼,其實這樣理解是不對的。看下面代碼其實鎖的是一個LayoutClass對象!那底層是怎麼實現的呢?
public static void add(){
synchronized (LayoutClass.class){
i++;
}
}
首先需要一個工具:看對象佈局的依賴文件
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
看代碼:
public class LayoutClass {
public static void main(String[] args) {
LayoutClass object = new LayoutClass();
System.out.println(ClassLayout.parseInstance(object).toPrintable());
}
}
看運行結果:
com.company.LayoutClass object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 05 c1 00 20 (00000101 11000001 00000000 00100000) (536920325)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
在64位操作系統中在開啓指針壓縮的情況下一個空對象佔用16個字節
什麼叫指針壓縮?
1.jdk1.6 update14開始,在64bit操作系統中,JVM支持指針壓縮
2.jvm配置參數:UseCompressedOops,compressed--壓縮、oop--對象指針
3.啓用指針壓縮:-XX:+UseCompressedOops,禁止指針壓縮:-XX:-UseCompressedOops
如果關閉對象的指針壓縮的內存佈局
com.company.LayoutClass object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 28 30 df 17 (00101000 00110000 11011111 00010111) (400502824)
12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
可以看到 對象頭佔用了16字節,其中MarkWord佔用8字節 ClassPointer佔用8字節
那開啓指針壓縮的好處是什麼?
首先在32位的操作系統是4字節,32位機器中的指針大小是32位,那32位可尋址的最大內存是2^32 差不多是4G
而在64位的操作系統中是8字節,64位機器的指針大小是64位,64位可尋址的最大內存是2^64 這個值是很大的
在32位的操作系統中最大的內存僅爲4GB所以,對堆的空間就產生了很大的限制,當應用程序進一步消耗內存的時候不得不擴大內存,而擴大內存的方式就是將32位升級爲64位,從而提供更大的尋址空間。雖然內存空間上來了,相應的也帶了了性能問題!
1,增加了GC開銷
2,增加了CPU尋址帶寬開銷
其實很好理解,內存佔用空間大了。CPU指針的空間大了。
如果開啓指針壓縮是什麼樣的?首先前面提到了 對象8字節對齊
比如:
(00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000) 指針地址:00 00 00 00
(00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000)