你能準確算出 new String("abc") 在 64 位 JDK 7 中佔用多少內存嗎?(壓縮指針 48B,未壓縮 64B)。本文將系統梳理 HotSpot VM 中對象的內存結構,並通過 Instrumentation API 實測驗證理論計算。
| 類型 | 大小 |
|---|---|
| boolean/byte | 1B |
| short/char | 2B |
| int/float | 4B |
| long/double | 8B |
| 引用(32位) | 4B |
| 引用(64位壓縮) | 4B |
| 引用(64位未壓縮) | 8B |
MySizeOf 類實現 premain 獲取 Instrumentation 實例agent.jar,Manifest 添加 Premain-Class: com.zzh.size.MySizeOfjavac -cp agent.jar ObjectSize.javajava -javaagent:agent.jar ObjectSizenew Object() = 12B Header + 4B Padding = 16B
// 壓縮關閉:16B Header + 4B 數據 + 4B Padding = 24B
class A { int a; } // 12 + 4 = 16B
class B { int a; int b; } // 12 + 8 = 20B → 24B (對齊)
Integer(1) // 12 + 4 = 16B
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
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 調優的基礎功力。