Java 記憶體管理 = 物件分配 + 物件回收。開發者負責 new,GC 負責識別「不可觸及」物件並回收堆記憶體。核心演算法:可達性分析 (GC Roots → 參考鏈)。
| 收集器 | 代別 | 演算法 | 特點 | 適用場景 |
|---|---|---|---|---|
| Serial | 新生代/老年代 | 複製/標記-整理 | 單執行緒、Stop-the-world (STW) | Client 模式、單核、嵌入式 |
| ParNew | 新生代 | 複製 | Serial 多執行緒版、需配合 CMS | 多核、舊版 CMS 搭配 |
| Parallel Scavenge | 新生代 | 複製 | 吞吐量優先、自適應調節 | 批次處理、科學計算、Java 8 預設 |
| CMS | 老年代 | 標記-清除 | 低停頓、併發、碎片化、CPU 敏感 | 響應時間敏感、Java 9 棄用、14 移除 |
| G1 | 全堆區域化 | 標記-整理+複製 | 可預測停頓、Region、記憶體佔用高 | 大堆 (6G+)、Java 9+ 預設 |
| ZGC | 全堆 | 染色指標+併發整理 | 亞毫秒停頓、支援 TB 級堆、Java 11+ | 超大堆、極低延遲要求 |
| Shenandoah | 全堆 | 併發整理+轉發指標 | 低停頓、無染色指標依賴、Java 12+ | 大堆、非 x86 平台 |
# 基礎堆設定
-Xms4g -Xmx4g # 固定堆大小,避免擴縮抖動
-Xmn1g # 新生代大小 (G1/ZGC 通常不設定)
# 收集器選擇
-XX:+UseG1GC # G1 (Java 9+ 預設)
-XX:+UseZGC # ZGC (Java 11+)
-XX:+UseShenandoahGC # Shenandoah (Java 12+)
# G1 關鍵調優
-XX:MaxGCPauseMillis=200 # 目標停頓 (預設 200ms)
-XX:G1HeapRegionSize=16m # Region 大小 1-32MB (2 的冪)
-XX:InitiatingHeapOccupancyPercent=45 # 觸發併發標記閾值 (預設 45%)
# ZGC/Shenandoah
-XX:ZCollectionInterval=5 # 最小收集間隔 (秒)
-XX:ConcGCThreads=4 # 併發 GC 執行緒數
# 通用診斷
-XX:+PrintGCDetails -XX:+PrintGCDateStamps
-Xlog:gc*:file=gc.log:time,uptime,level,tags # Java 9+ 統一日誌
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps
jstat、GCLogAnalyzer、Arthas、JProfiler 觀察分配率、晋升率、STW 時間。-Xms = -Xmx,避免擴縮觸發 Full GC。remove()| 誤區 | 真相 |
|---|---|
| System.gc() 能強制回收 | 僅建議,JVM 可忽略;生產嚴禁呼叫 |
| Finalizer 是釋放資源好地方 | 執行不可預測、阻塞 Finalizer 線程會 OOM、Java 9+ 棄用 |
| 弱引用/軟引用能解決 OOM | 只能緩解,根因在於產生速度 > 回收速度 |
| 參數抄襲網路「最佳配置」 | 負載特徵不同 (分配率、存活率、堆大小) 必須實測 |
| G1 設定 Region 越小越好 | 過小增加 Remembered Set 開銷,建議 4-32MB |
jcmd、jstat、jmap、jhat、JFR (Flight Recorder)、jconsole、VisualVMGC 調優不是玄學,而是「測量 → 假設 → 驗證 → 固化」的工程循環。優先從業務代碼減少分配壓力,再配合適合負載特徵的收集器與參數。記住:最好的 GC 是不需要跑的 GC。