首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 對象內存佈局與大小計算實戰指南

     編輯:Java 綜合教學

前言

你能準確算出 new String("abc") 在 64 位 JDK 7 中佔用多少內存嗎?(壓縮指針 48B,未壓縮 64B)。本文將系統梳理 HotSpot VM 中對象的內存結構,並通過 Instrumentation API 實測驗證理論計算。

對象內存三大區域

  1. 對象頭:包含 Mark Word(HashCode、GC 年齡、鎖狀態等)與類型指針。32 位 8B,64 位未壓縮 16B,開啟壓縮 12B(Mark 8B + Klass 4B)。
  2. 實例數據:字段數據,按聲明順序分配,父類字段在前。
  3. 對齊填充:HotSpot 要求對象大小為 8 字節倍數,不足補齊。

基本類型與引用佔用

類型大小
boolean/byte1B
short/char2B
int/float4B
long/double8B
引用(32位)4B
引用(64位壓縮)4B
引用(64位未壓縮)8B

Instrumentation 測量實戰

Agent 打包步驟

  1. 編寫 MySizeOf 類實現 premain 獲取 Instrumentation 實例
  2. 打包為 agent.jar,Manifest 添加 Premain-Class: com.zzh.size.MySizeOf
  3. 編譯測試類:javac -cp agent.jar ObjectSize.java
  4. 運行:java -javaagent:agent.jar ObjectSize

實測案例分析(64位 JDK 7,默認開啟壓縮)

案例 1:基礎對象

new Object() = 12B Header + 4B Padding = 16B
// 壓縮關閉:16B Header + 4B 數據 + 4B Padding = 24B

案例 2:自定義類與包裝類

class A { int a; }      // 12 + 4 = 16B
class B { int a; int b; } // 12 + 8 = 20B → 24B (對齊)
Integer(1)              // 12 + 4 = 16B

案例 3:數組對象(額外 4B 存長度)

int[2]   = 12 + 4(len) + 2×4 = 24B
int[3]   = 12 + 4 + 12 = 28B → 32B
char[2]  = 12 + 4 + 4 = 20B → 24B
char[3]  = 12 + 4 + 6 = 22B → 24B

案例 4:String 詳細拆解(JDK 7)

String 字段:char[] value, int hash, int hash32

sizeOf("a")      = 12 + 4×2 + 4 = 24B
fullSizeOf("a")  = 24B(String) + 24B(char[1]) = 48B
fullSizeOf("aaaaa") = 24B + 32B(char[5]) = 56B

// 未壓縮情況:64B / 72B

空 String 最小 40B(壓縮)/ 56B(未壓縮),建議優先使用基本類型而非包裝類。

附:核心測量代碼片段

public static long sizeOf(Object obj) {
    return inst.getObjectSize(obj); // 僅計算對象本體
}

public static long fullSizeOf(Object obj) throws IllegalAccessException {
    // 遞歸計算引用鏈上所有對象大小
    Set<Object> visited = new HashSet<>();
    Deque<Object> queue = new ArrayDeque<>();
    queue.add(obj);
    long size = 0;
    while (!queue.isEmpty()) {
        Object cur = queue.poll();
        if (cur == null || !visited.add(cur)) continue;
        size += inst.getObjectSize(cur);
        // 掃描字段與數組元素入隊...
    }
    return size;
}

結語

掌握對象內存佈局有助於優化大數據場景下的內存佔用,也是 JVM 調優的基礎功力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved