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