垃圾收集器:
Java的垃圾回收機制最主要的實現者就是”垃圾收集器”,但是每個廠商設計的虛擬機所提供的垃圾收集器都有很大區別,而且即使是同一個虛擬機也會提供幾個不同的垃圾收集器供用戶根據自己不同特點來組合。下圖是Hot Spot虛擬機包含的收集器,之后介紹每個收集器的特點。
在介紹各種收集器之前,先確認一下並行和並發的概念:(下面是指垃圾收集器的語境中)
l 並行(Parallel):多條垃圾收集線程並行工作,但此時用戶線程仍然處於等待狀態。
l 並發(Concurrent):用戶線程和垃圾收集線程同時執行(不一定是並行,可能是交替進行的),用戶程序繼續運行,而垃圾收集程序運行於另一個CPU上。
1.Serial收集器(新生代 – 串行GC)
最基本、最悠久的收集器,他是一個單線程的收集器,而單線程是指當他在進行垃圾收集的時候,必須暫停其他所有的工作線程,被稱為”Stop The World”。
優點:簡單而高效(與其他收集器的單線程相比),在限於單個CPU的環境,沒有額外的線程交互的開銷,所以能獲得最高效率。
適用:運行在Client模式下的虛擬機。
2.ParNew收集器(新生代 – 並行GC)
ParNew收集器其實就是Serial收集器的多線程版本,除了使用多條線程進行垃圾收集之外,其余的和Serial所有控制參數一樣。在配置為CMS GC的情況下默認的新生代收集器,可以用-XX:+UseParNewGC強制指定。
優點:在多CPU的環境下可以發揮更高而效率,並且是唯一一個可以和CMS收集器搭配工作的新生代並行GC。
適用:運行在server模式下的虛擬機首選的新生代收集器。
3.Parallel Scavenge收集器(新生代 – 並行回收GC)
看上去和ParNew沒什么區別,但是Parallel Scavenge最大的特點就是他的關注點在於CPU的吞吐量,吞吐量=運行代碼時間/(運行代碼時間+垃圾收集時間)。較高的吞吐量可以最好的利用CPU的效率。-XX:MaxGCPauseMillis配置最大垃圾收集停頓時間,-XX:GCTimeRatio配置吞吐量大小。
優點:被稱為”吞吐量優先”收集器,有一個自適應調節參數(-XX:+UseAdaptiveSizePolicy),當這個參數打開后,無需手動指定新生代大小(-Xmn)、Eden和Survivor比例(-XX:SurvivorRatio)、晉升老年代年齡限制(-XX:PretenureSizeThreshold)等細節參數,虛擬機會動態調節這些參數來提供最適合的停頓時間或最大吞吐量。
適用:本身是Server級別多CPU機器上的默認GC方式,也可以通過-XX:+UseParallelGC來指定,並且可以采用-XX:ParallelGCThread來指定線程數。
4.Serial Old收集器(老年代 – 串行GC)
Serial Old是Serial收集器的年老代版本,同樣是一個單線程收集器,使用”標記-整理”算法。
適用:Client模式下虛擬機使用;在Server模式有兩大用途:與Parallel Scavenge收集器搭配使用,作為CMS收集器的后備預案。
5.Parallel Old收集器(老年代 – 並行GC)
Parallel Old是Parallel Scavenge收集器的老年代版本,為了配合Parallel Scavenge的面向吞吐量的特性而開發的對應組合。
適用:在注重吞吐量以及CPU資源敏感的場合采用。
6.CMS收集器(老年代 – 並發GC)
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。基於”標記-清除”算法,整個過程分為4個步驟:初始標記(CMS initial mark)、並發標記(CMS concurrent mark)、重新標記(CMS remark)和並發清除(CMS concurrent sweep)。
其中初始標記、重新標記仍然是”Stop The World”,初始標記僅僅是標記一下GC Roots能直接關聯的對象,並發標記進行GC Roots Tracing的過程,重新標記為了修正並發標記期間因用戶程序繼續運行而導致標記產生變動的那部分對象,這個階段停頓時間比初始標記階段稍長一些,但比並發標記時間短。
優點:並發收集、低停頓。
適用:重視服務的響應速度、系統停頓時間和用戶體驗的互聯網網站或者B/S系統。
7.G1收集器
G1(Garbage First)收集器是當前收集器技術最前沿成果,與之前的CMS相比有兩個顯著改進:基於”標記-整理”算法實現收集器和精確控制停頓。能夠在基本不犧牲吞吐量的前提下完成低停頓的內存回收。
附:
默認GC組合:
可選的GC組合:
參考資料:
http://blog.csdn.net/zhangren07/article/details/6270895
http://www.blogjava.net/chhbjh/archive/2012/01/28/368936.html