天天看點

JVM4-記憶體布局

Java并發記憶體模型

JVM4-記憶體布局
使用JavaAgent測試Object的大小

對象大小(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)。

普通對象

  1. 對象頭:markword 8 ClassPointer指針:-XX:+UseCompressedClassPointers 為4位元組 不開啟為8位元組

HotSpot虛拟機對象的對象頭部分包括兩類資訊。第一類是用于存儲對象自身的運作時資料,如哈希(HashCode)、GC分代年齡、鎖狀态标志、線程持有的鎖、偏向線程ID、偏向時間戳等,這部分資料的長度在32位和64位的虛拟機(未開啟壓縮指針)中分别為32個比特和64個比特,官方稱它 為“Mark Word”。對象頭的另外一部分是類型指針,即對象指向它的類型中繼資料的指針。此外,如果對象是一個Java數組,那在對象頭中還必須有一塊用于記錄數組長度的資料。

  1. 執行個體資料
  1. 引用類型:-XX:+UseCompressedOops 為4位元組 不開啟為8位元組

    Oops Ordinary Object Pointers

  1. Padding對齊,8的倍數
    JVM4-記憶體布局

數組對象

  1. 對象頭:markword 8 ClassPointer指針同上 數組長度:4位元組
  2. 數組資料
  3. 對齊 8的倍數
    JVM4-記憶體布局

實驗

  1. 建立項目ObjectSize (1.8)
  2. 建立檔案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); } }

  3. src目錄下建立META-INF/MANIFEST.MF

    Manifest-Version: 1.0 Created-By: mashibing.com Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent

    注意Premain-Class這行必須是新的一行(回車 + 換行),确認idea不能有任何錯誤提示
  4. 打包jar檔案
  5. 在需要使用該Agent Jar的項目中引入該Jar包

    project structure - project settings - library 添加該jar包

  6. 運作時需要該Agent Jar的類,加入參數:

    -javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar

  7. 如何使用該類:

    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
      
JVM4-記憶體布局

Hotspot開啟記憶體壓縮的規則(64位機)

  1. 4G以下,直接砍掉高32位
  2. 4G - 32G,預設開啟記憶體壓縮 ClassPointers Oops
  3. 32G,壓縮無效,使用64位

    記憶體并不是越大越好(-)

對象定位​

  1. 句柄池
  2. 直接指針

配置設定過程

JVM4-記憶體布局