許多開發者初學 Java 時對「堆積」概念模糊,直到遭遇 java.lang.OutOfMemoryError: Java heap space 才被迫深入。本文梳理堆積記憶體的 10 個核心知識點,幫助建立完整認知體系,從容應對記憶體問題。
JVM 啟動時透過 -Xms/-Xmx 指定初始/最大堆積大小。32 位 JVM 受限於位址空間(通常 1.5~3GB),64 位理論無上限(受限於物理記憶體與 OS)。
基本型別區域變數在堆疊,但物件實體(含陣列、String、自訂類實例)一律在堆積。逃逸分析優化下,部分未逃逸物件可能被標量替換或棧上分配(JIT 編譯器決策)。
| 參數 | 含義 | 單位後綴 |
|---|---|---|
-Xms | 初始堆積大小 | M/G (如 512m, 2g) |
-Xmx | 最大堆積大小 | 建議 = -Xms 避免震盪 |
-Xmn | 新生代大小 | 約 1/4~1/3 -Xmx |
-XX:MaxMetaspaceSize | 元空間上限 (JDK8+) | 防止無限增長耗盡本機記憶體 |
注意:參數只能在 JVM 啟動時指定,運行期不可動態修改。
Runtime.getRuntime().maxMemory() (=-Xmx)、totalMemory() (當前已提交)、freeMemory() (當前空閒)。jmap -dump:format=b,file=heap.bin <pid> 產生二進位堆積快照(生產環境慎用,會 STW)。| 特性 | 堆積 | 堆疊 |
|---|---|---|
| 儲存內容 | 物件實例、陣列 | 區域變數、方法參數、返回位址、棧幀 |
| 生命週期 | GC 管理,不確定 | 隨方法進出自動分配/釋放,確定 |
| 分配速度 | 較慢 (指針碰撸/空閒列表) | 極快 (指針遞增) |
| 大小限制 | -Xmx 可達 GB 級 | -Xss 預設 1MB,較小 |
| 共享性 | 線程共享 | 線程私有 |
採用可達性分析判定垃圾(GC Roots 搜尋)。常見收集器:Serial、Parallel、CMS、G1、ZGC、Shenandoah。理解 Minor GC / Major GC / Full GC 觸發條件與停頓特徵,是調優前提。
Java heap space 還是 Metaspace/PermGen。-Xmx 是否過小,適度調大觀察是否緩解。jmap -histo:live)。# 1. 線上快速巡檢 GC 行為 (每 5 秒輸出一次)
jstat -gcutil 5000
# 2. 看存活物件 Top 20
jmap -histo:live | head -20
# 3. 導出堆積轉儲 (非高峰期操作,會 STW)
jmap -dump:format=b,file=/tmp/heap_$(date +%s).bin
# 4. MAT 開啟 .bin -> Leak Suspects Report -> 直達問題代碼
掌握這 10 點,你就擁有了從「認識堆積」到「解決 OOM」的完整知識骨架。記憶體問題本質上是物件生命週期管理失控,工具只是放大鏡,核心在於代碼層面的嚴謹設計:該釋放時釋放、該復用時復用、該流式處理時別一次性全載入。願你的 JVM 永遠健康運行!