理解物件記憶體佔用與引用語義是 JVM 調優與排查 OOM 的基礎。
空 Object 物件在堆中佔用 8 bytes (僅含物件頭)。程式碼:
Object ob = new Object();
總佔用:4 bytes (棧中引用) + 8 bytes (堆中物件) = 12 bytes。
所有非基本型別物件預設繼承 Object,故**任何物件大小 ≥ 8 bytes (堆中)**。
class NewObject {
int count; // 4 bytes
boolean flag; // 1 byte
Object ob; // 4 bytes (引用)
}
計算:8 (空物件) + 4 + 1 + 4 = 17 bytes。
對齊規則:JVM 物件記憶體分配按 8 的整數倍 對齊 → 最近的倍數為 24 bytes。
建議:盡量少用包裝類型。JDK 5.0+ 引入自動裝箱/拆箱,JVM 在儲存層面會優化,但邏輯層面仍需謹慎。
| 引用類型 | 建立方式 | GC 回收行為 | 典型用途 |
|---|---|---|---|
| 強引用 | Object obj = new Object(); |
嚴格判斷:被強引用 → **絕不回收** | 一般物件持有,預設行為 |
| 軟引用 | SoftReference<Object> ref = new SoftReference<>(obj); |
視**剩餘記憶體**決定:記憶體緊張 → 回收;充裕 → 保留 OOM 發生時,系統中必無軟引用存活 |
**記憶體敏感型快取** (圖片快取、資料緩衝) |
| 弱引用 | WeakReference<Object> ref = new WeakReference<>(obj); |
GC 時**必定回收**,生命週期僅存於**單次 GC 週期**內 | **非關鍵快取**、WeakHashMap 鍵、監聽器/回調持有 |
| 虛引用 | PhantomReference<Object> ref = new PhantomReference<>(obj, queue); |
無法單獨存活,**必須搭配 ReferenceQueue**;GC 時入隊列,供追蹤物件被回收時機 | 精確追蹤物件回收時機、DirectBuffer 清理、堆外記憶體管理 |
ReferenceQueue 處理不當易洩漏物件大小 = 物件頭 (8B) + 實例欄位 + 對齊填充 (8 的倍數)。包裝類型開銷極大,能用基本型別堅決不用包裝。四種引用類型賦予開發者與 GC 協作的精細控制力,善用軟/弱引用可構建記憶體友善的快取體系,虛引用則是堆外資源管理的關鍵槓桿。