JAVA是如何運行的四-對象佈局

首先說明爲什麼要學習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)

 

 

 

 

 


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章