什麼是 Java 堆?
JVM 啟動時向作業系統申請的記憶體區域,**所有 `new` 出來的物件都存放在堆中**。堆是垃圾回收 (GC) 的主要戰場。
如何調整堆大小
| 參數 | 含義 | 範例 |
-Xms | 初始堆大小 | -Xms256m |
-Xmx | 最大堆大小 | -Xmx1g |
-Xmn | 新生代大小 | -Xmn256m |
- 32 位 JVM 預設
-Xmx=64m(Solaris SPARC 例外)
- 64 位 JVM 預設約物理記憶體 1/4(最大)、1/16(初始)
- 生產環境建議固定 `-Xms=-Xmx` 避免動態擴縮容抖動
- 只能啟動時設定,運行期不可改
堆結構與 GC 代際

- 新生代:Eden + 2 個 Survivor,新物件誕生地,Minor GC 頻繁
- 老年代:長期存活物件晉升,Major/Full GC 耗時長
- 永久代 / 元空間:類元資料、常量池、靜態變數(JDK 8 移至 Metaspace,非堆)
兩類常見 OOM
java.lang.OutOfMemoryError: Java heap space — 堆不夠,物件太多或洩漏
java.lang.OutOfMemoryError: PermGen space / Metaspace — 類載入過多(動態代理、JSP、熱部署)
拋出前 JVM 已嘗試 Full GC 仍無法釋放足夠空間。
Heap Dump 獲取與分析
| 工具 | 用途 | 指令範例 |
jmap | 產生 dump 檔 | jmap -dump:live,format=b,file=heap.hprof <pid> |
jhat | 內建分析器(HTTP UI) | jhat -port 7000 heap.hprof |
| VisualVM / JProfiler / MAT | 圖形化深度分析 | 支援支配樹、洩漏疑點、歷史對比 |
10 大堆記憶體要點速查
- 堆是 OS 分配給 JVM 記憶體的一部分
- 所有物件實例儲存於堆
- 為 GC 便利,分新生代、老年代、永久代/元空間
- 用
-Xms/-Xmx/-Xmn 調整,單位加 m/g
- 可用
JConsole、Runtime.maxMemory()/totalMemory()/freeMemory() 監控
jmap 導出 dump,jhat/MAT 分析
- 堆 ≠ 棧(棧存呼叫框架、區域變數)
- GC 負責回收死物件記憶體回堆
- 偶發 OOM 先加大堆,頻發必查洩漏
- 善用 Profiler + Heap Dump 定位大物件、洩漏鏈
排查思路
- 確認是 Heap OOM 還是 Metaspace OOM
- 檢查 `-Xmx` 是否合理(建議 ≤ 物理記憶體 70%)
- 導出 Heap Dump,用 MAT 找 **Retained Size 最大** 的物件
- 查找 GC Roots 引用鏈,定位洩漏來源(靜態集合、ThreadLocal、未關閉資源、快取無淘汰)
- 修復代碼或調整 JVM 參數(如 `-XX:MaxMetaspaceSize`)
- 上一篇文章: Java 泛型通配符深度理解:置換原則、extends/super 差異與 PECS 原則實戰
- 下一篇文章: Java 執行緒安全核心:同步機制、鎖優化與無鎖思路實戰解析
Copyright ©
程式碼之家 All Rights Reserved