JVM 內存分代詳解
三大代劃分
- 年輕代:所有新對象誕生地,目標快速回收短命對象。分 Eden + 兩個 Survivor(From/To)。大部分對象在 Eden 分配,Eden 滿觸發 Minor GC,存活對象複製到 Survivor,再滿則複製到另一 Survivor,最終晋升老年代。Survivor 可配置多個延長對象在新生代壽命。
- 老年代:經歷 N 次 Minor GC 仍存活的對象進入,存放長壽命對象。
- 持久代:存類、方法等靜態數據,對 GC 影響小。動態生成類(如 Hibernate)需調大
-XX:MaxPermSize。
GC 類型
- Scavenge GC (Minor GC):Eden 分配失敗觸發,清理 Eden、整理 Survivor,不涉及老年代,頻繁快速。
- Full GC:對整個堆(Young + Tenured + Perm)整理,耗時長,調優核心在減少 Full GC。觸發條件:
- 老年代滿
- 持久代滿
- 顯式
System.gc()
- Heap 分配策略動態變化
實戰日誌分析
Exception in thread "http-bio-17788-exec-74" java.lang.OutOfMemoryError: PermGen space
明顯持久代 OOM,容器靜態類過多(JSP 編譯、Jar 包)。解決:增大 PermSize(默認 64M)。
JVM 內存參數速查
-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
-Xms 初始堆
-Xmx 最大堆
-XX:PermSize 初始非堆
-XX:MaxPermSize 最大非堆
堆 vs 非堆
堆:開發人員可用,存對象實例/數組。非堆:JVM 自用,存類元數據、常量池等。