jvm垃圾回收器cms和g1区别 JVM垃圾回收器

上篇我们知道垃圾回收机制,接下来,我们具体到垃圾回收器,看看JVM到底有哪些垃圾回收器 。
一.GC性能指标不可能三角

  • 吞吐量:运行用户代码的时间占总运行时间的比例
  • 暂停时间:进行GC时,用户线程被暂停的时间(STW)
  • 内存占用:JAVA堆所占内存的大小,这一点随着硬件的发展,越来越容易实现
主要矛盾:你要暂停时间短,你就需要频繁GC 。但是多次GC,会导致吞吐量低 。
jvm垃圾回收器cms和g1区别 JVM垃圾回收器

文章插图
二.七款垃圾回收器
  • 串行回收器:Serial,Serial Old
  • 并行回收器:ParNew,Parallel Scavenge,Parallel Old
  • 并发回收器:CMS,G1
接下来看它们几个的关系图:
jvm垃圾回收器cms和g1区别 JVM垃圾回收器

文章插图
 说明:
  • 红色虚线:jdk8废弃它们2组的组合
  • 绿色虚线:jdk14弃用Parallel Scavenge和Serial Old组合
  • 青色虚线:jdk14删除CMS回收器
【jvm垃圾回收器cms和g1区别 JVM垃圾回收器】接下来我们分别进行讨论
Serial/Serial Old
  • 最基本,最历史悠久的回收器
  • 串行回收器,Serial使用在新生代,Serial Old使用在老年代 。新生代采用复制算法,老年代使用标记压缩算法 。
  • 这种回收器只有在限定单核cpu才使用,现在已经很少使用了

jvm垃圾回收器cms和g1区别 JVM垃圾回收器

文章插图
ParNew
  • 并行回收器,多核情况下比Serial的要高,单核下没有Serial高 。
  • 用在新生代,采用复制算法 。老年代使用Serial Old

jvm垃圾回收器cms和g1区别 JVM垃圾回收器

文章插图
Parallel/Parallel Old
  • 吞吐量优先,java8默认的垃圾收集器
  • Parallel采用复制算法,Parallel Old采用标记压缩算法
  • Parallel与ParNew不同的是,Parallel目的为了达到一个可控的吞吐量,具有自适应调解策略
    • -XX:+UseAdaptiveSizePolicy: 开启自适应调节策略,年轻代的大小,eden,s的比例,,晋升老年代等参数会自动调节 。在手动调优比较困难的情况下,可以开启这种模式
  • 适用于后台运算而不需要太多交互的任务 。比如批量处理,订单处理,工资支付,科学计算等

jvm垃圾回收器cms和g1区别 JVM垃圾回收器

文章插图
 三.CMS回收器
  • CMS (Concurrent-Mark-Sweep)
  • 低延迟(低暂停时间),第一款并发回收器,但不代表没有STW
CMS的回收过程:CMS回收器的过程要比其他的都复杂,主要分为四个阶段:
  • 初始标记:只标记GC Roots直接关联的对象 。产生STW
  • 并发标记:从GC Roots直接关联的对象开始,向下遍历对象图 。不产生STW
  • 重新标记:为了修正在并发标记期间,用户线程产生的新的对象 。产生STW
  • 并发清除:标记-清除 。不产生STW
总结:在初始标记和重新标记阶段都会暂停用户线程,产生STW,但是STW的时间很短 。其他阶段都是并发进行,不产生STW 。所以CMS虽然是并发垃圾回收器,但是整体上还是会产生 STW,只是说STW的时间较短 。因为最费时的并发标记与清除标记都不需要暂停工作,所以整体 上的低暂停时间的
jvm垃圾回收器cms和g1区别 JVM垃圾回收器

文章插图
CMS的缺点:
  • 采用标记-清除算法会产生内存碎片
  • 对CPU资源敏感,CPU数量少会导致用户程序执行速度降低较多 。
  • 产生浮动垃圾,浮动垃圾就是在并发标记阶段产生的新垃圾 。虽然重新标记可以标记一些新产生的垃圾,但是对于GC Roots直接引用的对象(比如new),没有办法进行标记 。
那为什么不适应标记-压缩算法?
  • 因为在并发清除的时候,用户线程没有暂停 。如果使用标记整理算法,就需要移动用户线程在内存中的位置 。要保证用户线程正常使用,前提是它运行的资源不受影响,所以必须在STW情况下,才可以进行整理 。     
总结:关于内存碎片虽然也可以设置整理算法解决,但是效果不好 。垃圾回收过程中,必须暂停用户线程的时间 。而现在CMS要进行并发,那么就导致垃圾回收过程中,用户线程还在制造新的垃圾的现象 。所以CMS后来被移除掉了,就是因为它为了达到低延迟,牺牲了太多东西,也造成了太多的问题 。jdk9.0被移除,但是还可以用 。会报错。jdk14.0就彻底的被清除了 。
四.G1垃圾回收器
  • 分区回收器,并行与并发,同时还是分代收集(兼顾老年代和年轻代) 。
  • 将内存分为不同的区域(Region),在可控制的延迟时间下(让垃圾回收控制在一个时间段内),优先回收垃圾量最大的区域 。在延迟可控的情况下,尽可能获得高吞吐量 。(想着把吞吐量和暂停时间都尽可能的兼顾)
  • 主要是依靠的特色为:分区的原因,回收的范围小 。而且G1会把这些region放在一个优先列表中,每次垃圾回收,会在指定的时间内,收集最有价值的region区域 。达到高效的收集 。
  • Region之间是复制算法,整体上可以看作是标记压缩算法 。

jvm垃圾回收器cms和g1区别 JVM垃圾回收器

文章插图
寄语:坚持也是一种超能力