最近分析HotSpot VM GC日誌,就各類收集器的名稱搞暈掉了,幸虧參考R大(RednaxelaFX )一些回覆和文章。整理在此文,以方便自已往後查閱,也可以讓有須要的同窗少走彎路,追本溯源,一切從DefNew的來因提及。算法
DefNew: 是使用-XX:+UseSerialGC(新生代,老年代都使用串行回收收集器)時啓用oracle
ParNew: 是使用-XX:+UseParNewGC(新生代使用並行收集器,老年代使用串行回收收集器)或者-XX:+UseConcMarkSweepGC(新生代使用並行收集器,老年代使用CMS)時啓用。框架
本來HotSpotVM裏並無並行GC,當時只有NewGeneration。新生代,老年代都使用串行回收收集。後來準備加入新生代並行GC,就把NewGeneration更名爲DefNewGeneration,而後把新加的並行版叫作ParNewGeneration。ide
DefNewGeneration、ParNewGeneration都在Hotspot VM」分代式GC框架「內。但後來有個開發不肯意被這個框加憋着(證實了那句:全部壯舉都不是在框架內產生的),自已硬寫了個新的並行GC。測試後效果還不錯。因而這個也放入VM的GC中。這就是咱們如今看到的ParallelScavenge。性能
這個時候就出現個兩個新生代的並行GC收集器:ParNewGeneration,ParallelScavenge。測試
(R大: Scavenge或者叫scavenging GC,其實就是copying GC的另外一種叫法而已。HotSpot VM裏的GC都是在minor GC收集器裏用scavenging的,DefNew、ParNew和ParallelScavenge都是,只不過DefNew是串行的copying GC,然後二者是並行的copying GC。 由此名字就能夠知道,「ParallelScavenge」的初衷就是把「scavenge」給並行化。換句話說就是把minor GC並行化。至於full GC,那不是當初關注的重點。 )優化
把GC並行化的目的是想提升GC速度,也就是提升吞吐量(throughput)。因此其實ParNew與ParallelScavenge均可叫作Throughput GC。
可是在HotSpot VM的術語裏「Throughput GC」一般特指「ParallelScavenge」。spa
ParallelScavenge和ParNew都是並行GC,主要是並行收集young gen,目的和性能其實都差很少。最明顯的區別有下面幾點:日誌
ParallelScavenge之前是廣度優先順序來遍歷對象圖的,JDK6的時候改成默認用深度優先順序遍歷,並留有一個UseDepthFirstScavengeOrder參數來選擇是用深度仍是廣度優先。在JDK6u18以後這個參數被去掉,ParallelScavenge變爲只用深度優先遍歷。ParNew則是一直都只用廣度優先順序來遍歷。orm
ParallelScavenge完整實現了adaptive size policy,而ParNew及「分代式GC框架」內的其它GC都沒有實現完(倒不是不能實現,就是麻煩+沒人力資源去作)。因此千萬千萬別在用ParNew+CMS的組合下用UseAdaptiveSizePolicy,請只在使用UseParallelGC或UseParallelOldGC的時候用它。
因爲在「分代式GC框架」內,ParNew能夠跟CMS搭配使用,而ParallelScavenge不能。當時ParNew GC被從Exact VM移植到HotSpot VM的最大緣由就是爲了跟CMS搭配使用。
在ParallelScavenge成爲主要的throughput GC以後,它還實現了針對NUMA的優化;而ParNew一 直沒有獲得NUMA優化的實現。
上面說ParallelScavenge並行收集young gen,那old/perm gen呢?
ParallelScavenge由於和其餘幾個GC不在一個框架內,最初的ParallelScavenge體系對老年代的回收拿的是VM的「分代式框架「裏在 Serial Old收集器的代碼,改了接口,負責full GC,
並命名爲: PSMarkSweep(=「ParallelScavenge的MarkSweep」),其實就是仍然串行收集。
這裏的ParallelScavenge已經不是Parallel Scavenge(並行新生代收集器),而是一套GC框架體系。
爲了名稱與VM「分代式框架」裏的收集器好區別,在這套體系時,新生代收集器叫:PSScavenge,老年代收集器叫:PSMarkSweep。(PS當作是ParallelScavenge縮寫,做爲前綴)。
後來,由於未知的緣由,老年代GC的並行化,沒有在VM」分代式GC框架「中完成,而選擇了在ParallelScavenge框架中。其成果就是使用了LISP2算法的並行版的full GC收集器,名爲PSCompact(=「ParallelScavenge-MarkCompact」),收集整個GC堆。
當啓用-XX:+UseParallelOldGC時,用的就是PSScavenge+PSCompact的組合。
當啓用-XX:+UseParallelGC時,用的就是PSScavenge+ PSMarkSweep的組合。
(在Jconsole查看時,PSCompact、PSMarkSweep都顯示爲PSMarkSweep
DefNew顯示爲Copy,Serial Old(MSC)顯示爲MarkSweepCompact)。
Guest Author有一幅關於GC收集器的示意圖:
×××部分的用於新生代的收集器,紫灰色部分的用於老年代的收集器。鏈接線表示二者能夠配合使用。
你會發現分代式GC框架有收集器(Serial (就是DefNew),ParNew,CMS,MSC)能夠任意搭配。而ParallelScavenge體系裏的PSScavenge(圖示中的ParallelScavenge),只能和其同一體系的Parallel Old搭配。
至於ParallelScavenge和Serial Old的連線,就是由於上文提到的PSMarkSweep,他是從VM「分代式框架「裏抽出來的Serial Old收集器,加了一層包裝而已。
?號那個應該就是如今G1,他又是另外一個體系框架內開發的,因此六親不認。