最近分析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,他又是另外一个体系框架内开发的,因此六亲不认。