1. 程式人生 > >HotSpot VM GC收集器的合名問題

HotSpot VM GC收集器的合名問題

java gc

最近分析HotSpot VM GC日誌,就各種收集器的名稱搞暈掉了,幸好參考R大(RednaxelaFX )一些回復和文章。整理在此文,以方便自已日後查閱,也可讓有需要的同學少走彎路,追本溯源,一切從DefNew的來因說起。


DefNew: 是使用-XX:+UseSerialGC(新生代,老年代都使用串行回收收集器)

ParNew: 是使用-XX:+UseParNewGC(新生代使用並行收集器,老年代使用串行回收收集器)或者-XX:+UseConcMarkSweepGC(新生代使用並行收集器,老年代使用CMS)

原本HotSpotVM裏並沒有並行GC,當時只有NewGeneration。新生代,老年代都使用串行回收收集。後來準備加入新生代並行

GC,就把NewGeneration改名為DefNewGeneration,然後把新加的並行版叫做ParNewGeneration

DefNewGenerationParNewGeneration都在Hotspot VM”分代式GC框架“內。但後來有個開發不願意被這個框加憋著(證明了那句:所有壯舉都不是在框架內產生的),自已硬寫了個新的並行GC。測試後效果還不錯。於是這個也放入VMGC中。這就是我們現在看到的ParallelScavenge

這個時候就出現個兩個新生代的並行GC收集器:ParNewGenerationParallelScavenge

(R大: Scavenge或者叫

scavenging GC,其實就是copying GC的另一種叫法而已。HotSpot VM裏的GC都是在minor GC收集器裏用scavenging的,DefNewParNewParallelScavenge都是,只不過DefNew是串行的copying GC,而後兩者是並行的copying GC 由此名字就可以知道,“ParallelScavenge”的初衷就是把“scavenge”給並行化。換句話說就是把minor GC並行化。至於full GC,那不是當初關註的重點。 )

GC並行化的目的是想提高GC速度,也就是提高吞吐量(throughput)。所以其實ParNewParallelScavenge

都可叫做Throughput GC
但是在HotSpot VM的術語裏“Throughput GC”通常特指“ParallelScavenge”

ParallelScavengeParNew都是並行GC,主要是並行收集young gen,目的和性能其實都差不多。最明顯的區別有下面幾點:

  1. ParallelScavenge以前是廣度優先順序來遍歷對象圖的,JDK6的時候改為默認用深度優先順序遍歷,並留有一個UseDepthFirstScavengeOrder參數來選擇是用深度還是廣度優先。在JDK6u18之後這個參數被去掉,ParallelScavenge變為只用深度優先遍歷。ParNew則是一直都只用廣度優先順序來遍歷。

  2. ParallelScavenge完整實現了adaptive size policy,而ParNew分代式GC框架內的其它GC都沒有實現(倒不是不能實現,就是麻煩+沒人力資源去做)。所以千萬千萬別在用ParNew+CMS的組合下用UseAdaptiveSizePolicy,請只在使用UseParallelGCUseParallelOldGC的時候用它。

  3. 由於在分代式GC框架內,ParNew可以跟CMS搭配使用,而ParallelScavenge不能。當時ParNew GC被從Exact VM移植到HotSpot VM的最大原因就是為了跟CMS搭配使用。

  4. ParallelScavenge成為主要的throughput GC之後,它還實現了針對NUMA的優化;而ParNew一 直沒有得到NUMA優化的實現

上面說ParallelScavenge並行收集young gen,那old/perm gen呢?

ParallelScavenge因為和其他幾個GC不在一個框架內,最初的ParallelScavenge體系對老年代的回收拿的是“VM分代式框裏的“ Serial Old收集器,改了接口,負責full GC

命名為: PSMarkSweep(=“ParallelScavengeMarkSweep”),其實就是串行收。

這裏的ParallelScavenge已經不是Parallel Scavenge,而是一套GC框架體系。

為了名稱下好區別,在這套體系時,新生代收集器叫:PSScavenge,這時的老年代收集器叫:PSMarkSweep(PS看成是ParallelScavenge縮寫,作為前綴)

後來,因為未知的原因,老年代GC的並行化,沒有在分代式GC框架“中完成,而選擇了在ParallelScavenge框架中。其成果就是使用了LISP2算法的並行版的full GC收集器,名為PSCompact(=“ParallelScavenge-MarkCompact”),收集整個GC

當啟用-XX:+UseParallelOldGC時,用的就是PSScavenge+PSCompact的組合

當啟用-XX:+UseParallelGC時,用的就是PSScavenge+ PSMarkSweep的組合

(在Jconsole查看時,PSCompactPSMarkSweep都顯示為PSMarkSweep)。


Guest Author有一幅關於GC收集器的示意圖:

技術分享

黃色部分的用於新生代的收集器,紫灰色部分的用於老年代的收集器。連接表示兩個可以配合使用。


你會發現分代式GC框架有收集器(Serial (就是DefNew),ParNewCMSMSC)可以任意搭配。而ParallelScavenge體系裏的PSScavenge(圖示中的ParallelScavenge),只能和其同一體系的Parallel Old搭配

至於ParallelScavengeSerial Old的連線,就是因為上文提到的PSMarkSweep,他是從“VM分代式框裏的“ 抽出來的Serial Old收集器,加了一層包裝而已。

?號那個應該就是現在G1,他又是另一個體系框架內開發的,所以六親不認

本文出自 “天下無賊” 博客,請務必保留此出處http://guojuanjun.blog.51cto.com/277646/1954570

HotSpot VM GC收集器的合名問題