Java并發記憶體模型
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iYxkjMkBjNxIWMiRTNwU2NjV2NzIDZmNTZmJWO5IWOz8CX2EzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL5M3Lc9CX6MHc0RHaiojIsJye.png)
對象大小(64位機)
觀察虛拟機配置
java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=133199488 -XX:MaxHeapSize=2131191808 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
對象的記憶體布局
在HotSpot虛拟機裡,對象在堆記憶體中的存儲布局可以劃分為三個部分:對象頭(Header)、執行個體資料(Instance Data)和對齊填充(Padding)。
普通對象
- 對象頭:markword 8 ClassPointer指針:-XX:+UseCompressedClassPointers 為4位元組 不開啟為8位元組
HotSpot虛拟機對象的對象頭部分包括兩類資訊。第一類是用于存儲對象自身的運作時資料,如哈希(HashCode)、GC分代年齡、鎖狀态标志、線程持有的鎖、偏向線程ID、偏向時間戳等,這部分資料的長度在32位和64位的虛拟機(未開啟壓縮指針)中分别為32個比特和64個比特,官方稱它 為“Mark Word”。對象頭的另外一部分是類型指針,即對象指向它的類型中繼資料的指針。此外,如果對象是一個Java數組,那在對象頭中還必須有一塊用于記錄數組長度的資料。
- 執行個體資料
-
引用類型:-XX:+UseCompressedOops 為4位元組 不開啟為8位元組
Oops Ordinary Object Pointers
- Padding對齊,8的倍數
JVM4-記憶體布局
數組對象
- 對象頭:markword 8 ClassPointer指針同上 數組長度:4位元組
- 數組資料
- 對齊 8的倍數
JVM4-記憶體布局
實驗
- 建立項目ObjectSize (1.8)
- 建立檔案ObjectSizeAgent
package com.mashibing.jvm.agent; import java.lang.instrument.Instrumentation; public class ObjectSizeAgent { private static Instrumentation inst; public static void premain(String agentArgs, Instrumentation _inst) { inst = _inst; } public static long sizeOf(Object o) { return inst.getObjectSize(o); } }
- src目錄下建立META-INF/MANIFEST.MF
注意Premain-Class這行必須是新的一行(回車 + 換行),确認idea不能有任何錯誤提示Manifest-Version: 1.0 Created-By: mashibing.com Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent
- 打包jar檔案
-
在需要使用該Agent Jar的項目中引入該Jar包
project structure - project settings - library 添加該jar包
- 運作時需要該Agent Jar的類,加入參數:
-javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar
- 如何使用該類:
package com.mashibing.jvm.c3_jmm; import com.mashibing.jvm.agent.ObjectSizeAgent; public class T03_SizeOfAnObject { public static void main(String[] args) { System.out.println(ObjectSizeAgent.sizeOf(new Object())); System.out.println(ObjectSizeAgent.sizeOf(new int[] {})); System.out.println(ObjectSizeAgent.sizeOf(new P())); } //一個Object占多少個位元組 // -XX:+UseCompressedClassPointers -XX:+UseCompressedOops // Oops = ordinary object pointers private static class P { //8 _markword //4 _class pointer int id; //4 String name; //4 int age; //4 byte b1; //1 byte b2; //1 Object o; //4 byte b3; //1 } }
16
16
32
Process finished with exit code 0
Hotspot開啟記憶體壓縮的規則(64位機)
- 4G以下,直接砍掉高32位
- 4G - 32G,預設開啟記憶體壓縮 ClassPointers Oops
-
32G,壓縮無效,使用64位
記憶體并不是越大越好(-)
對象定位
- 句柄池
- 直接指針