虛擬機有許多的垃圾收集器可以選擇,這裏簡單的記錄分享下每個收集器的特點
一、Serial
- 歷史最久,曾經是新生代唯一選擇
- 單線程,進行時暫停所有用戶線程-Stop The World
- Client模式下默認新生代收集器
- 單個線程更加高效簡單,沒有線程交互開銷,一般client應用內存使用不大,停頓時間很短
二、ParNew
- Serial的多線程版本,控制參數、收集算法、Stop The World、對象分配策略、回收策略相同
- 新生代收集器
- 除了Serial已外,只有ParNew可以與CMS配合使用
- 單CPU環境下,性能差於Serial
- 默認下GC線程數與CPU數相同,可配置(-XX: ParallelGCThreads)
三、Parallel Scavenge
- 新生代收集器,採用複製算法
- 並行多線程收集
- 目標不是縮短停頓時間,而是達到可控制的吞吐量:CPU運行用戶線程時間與CPU總消耗時間比
- 爲了更高效率利用CPU時間
- 兩個參數控制吞吐量:最大停頓時間:-XX:MaxGCPauseMillis(>0),直接吞吐量大小:-XX:GCTimeRatio(0~100)
- 儘可能保證停頓時間不超過設置值,
- 短停頓時間以犧牲吞吐量和新生代空閒換取,GC更頻繁,吞吐量下降
- GCTimeRatio 吞吐量倒數,默認值99,即最大1% GC時間
- 吞吐量優先
- 自動化開關參數:-XX:+UseAdaptiveSizePolicy,不需手動設置新生代大小(-Xmn)、Eden與Survivor區比例(-XX:SurvivorRatio)、晉升老年代年齡(-XX:PretenureSizeThreadhold),虛擬機GC自適應調節策略:動態調整這些參數提供最適合的停頓時間或最大吞吐量
- 同是多線程並行,自適應調節是與ParNew最大的區別
四、Serial Old
- Serial的老年代版本
- 單線程
- 標記-整理 算法
- 主要用於Client模式
五、Parallel Old
- Parallel Scavenge 老年代版本
- 並行多線程
- 標記-整理 算法
- 在此收集器發佈前,Parallel Scavenge 只能與Serial Old配置使用,二Serial Old在服務端應用性能較差
- 與Parallel Scavenge 配合,吞吐量優先
六、CMS
- Concurrent Mark Sweep,併發低停頓
- 以最短停頓時間爲目標
- 標記-清除 算法
- 收集四個階段:初始標記、併發標記、重新標記、併發清除
- 初始標記:Stop The World,快速標記GC Roots直接關聯對象
- 併發標記:併發可達性分析
- 重新標記,Stop The World,修正併發階段對象引用變動導致的變更
- 最耗時的併發標記、併發清除可以與用戶線程一起工作
- 對CPU資源敏感,多線程併發程序通常都是這樣,當CPU數少,或CPU資源緊張,性能下降
- 無法處理浮動垃圾,可能出現Concurrent Mode Failure 導致另一次Full GC;
- 浮動垃圾(Floating Garbage):併發清理階段用戶線程還在運行,這個階段新產生的垃圾不會在該次GC回收,因爲已經過了標記階段;
- 不可在老年代幾乎用完才啓動GC,必須保留較大一部分空間,用於GC中程序繼續運行所需,默認68%
- 通過-XX:CMSInitiatingOccupancyFraction控制這個百分比,設置過高會導致“Concurrent Mode Failure”,過低又導致頻繁GC
- CMS GC期間,出現內存不出會出現“Concurrent Mode Failure”失敗,虛擬機將會啓動後背方案,保證內存分配:臨時啓動Serial Old 重新一次老年代GC,導致長停頓
- 標記-清除 算法導致內存碎片,大對象分配難,導致頻繁GC,運行控制Full GC 時開啓合併整理,但是會導致停頓時間加長
七、G1(Garbage-First)
- JDK1.7 最新,面向服務端應用
- 併發、並行:充分利用多CPU
- 分代收集,可管理整個堆,包括新生代和老年代
- 標記-整理 、複製 算法,GC不產生碎片
- 低停頓,可預測停頓時間模式
- 內存分區域管理(保留新生代和老年代概念)
- 分區域進行GC,避免全區域GC,高回收價值區域(單位時間內回收更多的內存空間)優先回收,可控制停頓時間