为什么Java8不使用CMS作为默认垃圾收集器
一般的垃圾回收器搭配为:
Serial New + Serial Old
ParNew + CMS + Serial Old
Parallel Scavenge + Parallel Old
G1
shenandoah
zgc
历代版本的默认收集器始终没有使用CMS作为默认收集器,在jdk9 G1成为default gc策略之后,CMS就被deprecated,然后在14被正式从jdk中删除。Java官方做出这样的决定肯定是有原因的,虽然CMS相比Parallel是后推出的收集器,但并不意味CMS比Parallel强。
CMS是关注低延迟的收集器,Parallel是关注高吞吐量的收集器,在一般的服务端中大型系统中,高吞吐量仍然是很多程序追求的重点,况且linux和网络本身就就会有停顿,造成延迟的效果。
-
CMS在GC时会对CPU有比较大的压力,形成典型的CPU Spike。
-
CMS仅针对老年代,还需要一个年轻代的收集器。CMS又和Parallel
-
Scavenge不兼容,只能和ParNew凑合,然而ParNew又不如Parallel Scavenge先进。
-
CMS没法处理浮动垃圾,并发标记过程中死亡的对象只能留到以后的GC处理。
-
Mark-Sweep算法对内存碎片无能为力,并发又如何?内存碎片太多,触发了Concurrent Mode Failure还不是得去请Serial Old来收拾烂摊子?结果就是stop the world。
…以上的种种,造成的结果就是ParNew+CMS+Serial Old的组合工作起来其实并不稳定。为了得到CMS那一点好处,需要付出很多的代价(包括JVM调参)。所以作为默认GC,采用Parallel Scavenge/Parallel Old这种省心又省力方案完全合理。况且之后出现的G1收集器无需复杂的配置即可达到很高的综合性能,CMS就更没必要了。
参考:https://www.zhihu.com/question/418331009