| 維度 | C++ | Java |
|---|---|---|
| 原因 | `new` 後未 `delete`,物件永佔堆 | **無意識引用保持**:物件還被引用 (如集合、靜態欄位),GC 認為「存活」拒絕回收 |
| 機制 | 手動管理 | GC 自動管理 (可達性分析) |
| 典型代碼 | `void f() { int* p = new int[5]; }` | `Vector v = new Vector(); for(i) { Object o=new Object(); v.add(o); o=null; } // o 雖 null,但 v 仍引用` |
Profiler 提供兩大視圖:
| 視圖 | 用途 |
|---|---|
| Instance Reference Graph (引用圖) | 顯示從洩漏物件**反向追溯到 GC Root** 的完整引用鏈。第二欄即逆向鏈。 |
| Instance Allocation Graph (分配圖) | 統計物件**分配位置** (哪個方法 `new` 出來)。 |
分析步驟:
class Logger {
static Map temp = new HashMap<>(); // GC Root
static void log(String msg) {
String key = Thread.currentThread() + System.currentTimeMillis();
temp.put(key, msg); // 建立引用鏈
// 邏輯錯誤:currentTimeMillis() 變化導致 key 不匹配,刪除失效
temp.remove(Thread.currentThread() + System.currentTimeMillis());
}
}
引用鏈:`Logger.temp (static)` → `HashMap.Entry` → `msg (String)` → 洩漏。
修復:用 `ThreadLocal` 儲存 key、或 `try-finally` 確保刪除、或改用弱引用 `WeakHashMap`。
OptimizeIt 已停更,推薦:
Java 內存洩漏 = **無意識引用保持**。檢測核心流程:**周期性快照 → 實例增長趨勢判定 → 引用圖反向追溯 GC Root → 分配圖定位代碼行 → 修復多餘引用**。掌握此法,配合現代工具,任何 Java 系統穩定性難題皆可攻克。