《Java 底層原理》Jvm對象結構和指針壓縮

前言

Java 程序調優是一個程序員必備的技能。

對象內存結構

對象頭:

    Mark Word :32bit機 4B;64bit機 8B 是固定的。

    類型指針:klass pointer,引用類型在方法區的地址。 開啓指針壓縮佔4字節,不開啓佔8個字節。

    數組長度:對象不是數組佔0字節,對象是數組佔4字節,開啓指針壓縮,數組長度會放到類型指針的後半段

    對其填充:在關閉指令壓縮的情況下,數組類型還會進行填充,稱爲兩段填充,還有很多中情況會出現填充。

實例數據:

    類的非靜態屬性,基礎數據類型(byte 1字節,int 4字節,等等),引用類型:開啓指針壓縮4B,不開8字節。

對齊填充:

    保證Java對象的大小都是8字節的整數倍,不足就不起, 例如對象前面的信息計算下來是31個字節,那就會補一個字節成32個字節。對齊填充的出現原因和內存分配有關,不需要獲取哦對象信息還要去多塊內存獲取組合。

計算對象大小

百度網盤: https://pan.baidu.com/s/1bk_qdV1jpo7qSBnLGJHgcw 提取碼: jafj     下載一個Jar包。

import org.openjdk.jol.info.ClassLayout;

public class JvmTest4 {

    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(ClassLayout.parseInstance(student).toPrintable());
    }
}

運行結果:

-XX:+/-UseCompressedOops   -- 開啓或者關閉指針壓縮。

案例

import org.openjdk.jol.info.ClassLayout;

public class JvmTest4 {

    static int[] a = new int[]{1,2,3};

    public static void main(String[] args) {
        System.out.println(ClassLayout.parseInstance(a).toPrintable());
    }
}

運行結果:

這個案例是關不指針壓縮下運行的, 可以很好的看到有兩階段提交的功能。

指針壓縮

因爲Java對象是8字節對齊的,所有對象對應的字節最後3位一定是000,故存儲的時候可以去掉後面3個0。

面試題:Java堆內存最大允許多少,爲什麼?

對象頭中的類型指針指向的就是對象引用變量在方法區的地址,通過這個地址可以找到整個對象的全部內容在內存中位置。

類型指針在開啓指針壓縮的情況下,佔用4個字節即32位,2的32次方就是4G,類型指針最大可以存在4G內存的位置。 又因爲每個對象在開啓指針壓縮的情況下,最後3位000會被去掉。 所以實際4個字節可以表示 2的35次方-2的3次方的最大內存地址,即32G內存的最大位置。

因爲現在都是64位機器了,那麼如果電腦或者服務器的內存超過32G內存,在開啓指針壓縮的情況下就是出現找不到內存地址情況?

如果在開啓指針壓縮下優化這個問題,可以將Java對象的8字節對齊改成16字節對其,甚至32字節對其。這個能表示的內存最大值就是64G,128G了。 這個需要修改JDK源碼。

總結

Jvm的對象的結構,指針壓縮對我們後續遇到問題,能夠提供非常好的基礎鋪墊。

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