1. 程式人生 > 其它 >Jvm物件結構和指標壓縮 《Java 底層原理》Jvm物件結構和指標壓縮

Jvm物件結構和指標壓縮 《Java 底層原理》Jvm物件結構和指標壓縮

抄錄於 https://www.cnblogs.com/jssj/p/14348271.html

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

閱讀目錄

回到目錄

前言

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