jvm在长时间的演变过程中出现了很多垃圾回收器,在这里总结一下
1. 7种经典垃圾回收器
串行垃圾回收器: Serial,Serial Old(回收老年代)
并行垃圾回收器: ParNew, Parallel Scavenge, Parallel Old(回收老年代)
并发垃圾回收器: CMS,G1
2. 垃圾回收器的演变过程
- 1999年jdk1.3 第一款垃圾回收器 Serial串行垃圾回收器, ParNew是Serial的多线程版本
- 2002年jdk1.4 发布 Parallel 和 CMS(Concurrent Mark Sweep)垃圾回收器
- jdk1.6 默认垃圾回收器 Parallel
- 2012年jdk1.7 发布G1
- 2017 jdk9 默认垃圾回收器G1 替代CMS
- 2018年3月 jdk10 G1增加并行垃圾回收
- 2018年9月 jdk11发布 增加ZGC
- 2019年3月 jdk12增强G1, OpenJdk中新增RedHat开发的Shenandoah垃圾回收器(低延迟)
- 2019年9月 jdk13发布增强ZGC
- 2020年3月 jdk14发布,删除CMS,扩展ZGC在mac和win上的应用.
可以总结,在jdk9之前一直用的 Parallel垃圾回收器,即Parallel Scavenge+Parallel Old的集合
jdk9之后开始使用G1
未来可能使用ZGC
3. 垃圾回收器和垃圾分代之间的关系
jvm是分代的,那么垃圾回收器也会针对不同的分代区域进行回收
新生代回收: Serial, Parallel Scavenge, ParNew
老年代回收: Serial Old, Parallel Old, CMS
整堆回收: G1
3.1 组合关系
既然垃圾回收器也是基于分代思想的,那么垃圾回收器肯定要组合使用,组合关系如下:
- 蓝色的为新生代垃圾回收器
- 橘色为老年代垃圾回收器
- G1特殊,既可以回收新生代又可以回收老年代
- 红色虚线为jdk8之前(不包含jdk8)存在的组合关系,jdk8之后移除 例如Serial+CMS; ParNew+Serial Old
- 绿色的虚线为jdk14之后移除的组合关系其中CMS在jdk14之后彻底移除
- CMS和Serial Old同为老年代回收器,未什么同时使用?
- SerialOld是CMS的后备方案,用来处理当CMS回收失败的时候再次回收
- CMS因为是并发的垃圾回收器,在多个线程交替执行的时候,可能存在回收失败的情况(这也可以看作并发垃圾回收器的缺点之一).
3.2 为什么要有组合关系
疑问:
为什么需要多个垃圾回收器组合使用,既然G1是最先进的垃圾回收器,为什么不把其他的垃圾回收器全部删除掉,启用G1呢?
理解:
java是一个适用于多平台多环境的语言,jvm可能运行在各种情况下,而在不同的情况下需要不同的垃圾回收器,
例如: 在单核cpu的情况下,Serial的性能反而较好,因为jvm运行在只有一个线程的处理器上,那也谈不上并发了.
同理在不同的应用场景下需要有不同的垃圾处理器,正如上文所说,垃圾处理器的优化方向是低延迟和吞吐量,那在不同的场景下对这两种方向需求程度可能不一致
例如: java作为移动端使用的时候,我们为了提高用户体验,可能对低延迟要求更高; 而作为一个服务端提供服务时,可能会稍微降低对延迟的要求,而是提高吞吐量的需求,这个时候就需要按需组合垃圾回收器的关系,从而更加符合我们的需求.
总结:
没有一个完美的垃圾回收器,只有最符合需求的垃圾回收器.