JVM內存結構
根據Java虛擬機規范,JVM內存主要劃分為以下區域:
-
年輕代(New Generation)
- 包括Eden空間,用于存放新創建的對象。
- Survivor區由兩個相同大小的Survivor1和Survivor2組成,用于存放經過初次垃圾回收后仍然存活的對象,通過“ survivor-to-survivor ”的過程提升對象年齡,最終符合條件的對象會被移到年老代。
-
年老代(Tenured Generation)
- 存放從年輕代中經歷多次垃圾回收仍然存活的對象。
-
永久代/元數據區(Permanent Generation/Metaspace)
- 在Java 8及以后版本中,永久代被元數據區取代,用于存儲類、方法等元數據信息。可通過
-XX:MetaspaceSize
和-XX:MaxMetaspaceSize
參數調整其大小。 - 在早期版本中,永久代大小推薦初始設置為128M,并預留30%的增長空間。
- 在Java 8及以后版本中,永久代被元數據區取代,用于存儲類、方法等元數據信息。可通過
垃圾收集算法
JVM的垃圾回收基于“標記-清除”或其衍生算法,具體包括:
- Serial算法:單線程回收,適用于單CPU環境,執行時會暫停所有用戶線程。
- Parallel算法(并行回收):多線程并行回收,適用于多CPU環境,回收時暫停用戶線程,但多個線程并行工作加速回收過程。
- Concurrent算法(并發回收):多線程回收,與應用程序并發執行,減少暫停時間,適用于對響應時間敏感的應用。
垃圾回收觸發條件
- 當年輕代空間(特別是Eden區)填滿時,觸發Minor GC,只清理年輕代。
- 當年老代或元數據區滿時,觸發Full GC,同時回收年輕代和年老代(或進行元數據區的清理)。
OutOfMemoryError異常
JVM在以下情況可能拋出OutOfMemoryError
異常:
- 年輕代、年老代或元數據區空間耗盡,且無法通過回收獲得足夠的空間。
- 即使JVM并未完全耗盡內存,但在連續幾次GC后,回收的內存比例小于2%,且JVM花費超過98%的時間在GC上,表明內存已極度碎片化,無法有效利用。
此機制設計旨在允許程序在崩潰前有機會執行最后的操作,例如輸出堆轉儲(Heap Dump),便于后續分析故障原因。