《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的對象的結構,指針壓縮對我們后續遇到問題,能夠提供非常好的基礎鋪墊。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM