JVM7:常见的垃圾回收器

常见的垃圾回收器:

    • Serial
    • Serial Old
    • Parallel Scavenge
    • Parallel Old
    • ParNew
    • CMS
    • G1
    • ZGC
    • Shenandoah
    • Epsilon

下图已经列出来了这,其中Epsilon是debug使用的,不用过分关注;最常见的组合有:Serial +Serial Old 、Parallel Scavenge + Parallel Old 、ParNew + CMS。G1之前都是不仅在逻辑上是分代的而且在物理层面上也是分代的;G1只是在逻辑上分代;G1之后完全不分代,但是在生产环境使用的很少;

 1、Serial

当垃圾收集器工作时所有工作线程全部停止,这里线程停下来一定会停在一个安全点上;

safe-point :线程停止(需要找到一个安全点上线程停止),因为停顿的时间长,现在很少用;

 2、Serial Old 

这个垃圾收集器用在老年代,它用的是mark-sweep的算法,他用的是单线程;

a stop-the-world 

mark-sweep-compact  collector that uses a single GC thread(使用单个GC线程的标记-清理-收集器).

3、Parallel Scavenge

a stop-the-world 

Copying collector which uses multiple GC threads(使用多个GC线程的复制收集器).

 如果你在JVM没有做任何的调优的话,默认使用的是:parallel scavenge +parallel old  简称(ps + po)

Parallel Scavenge 与Serial的区别:Parallel Scavenge 是多线程清理垃圾,后者为单线程清理垃圾。

4、Parallel Old 

a compacting collector that uses multiple GC threads(使用多个GC线程的压缩收集器).

整理算法

5、ParNew

其实就是parallel new 的意思,和Parallel Scavenge没有很大的区别,就是它的新版本,做了一些的增强以便能够让它和CMS有更好的配合使用,CMS在某个特定的阶段会和Parallel New 同时运行。在工作的时候其余的线程不能够工作,必须等GC回收器结束后才可以。

Parallel New 和 Parallel Scavenge 区别:

    • parallel new 的响应时间优先
    • 能够配合CMS
    • parallel scavenge 的吞吐量优先

6、CMS

CMS非常重要,它诞生了一个里程碑,以前的垃圾回收器在工作的时候其他的线程都要停下来,等我工作完,才能工作,CMS的出现消除了这个问题,与此同时CMS也带来了很多问题,以至于目前的所有的JDK版本默认都不是使用它。

    • CMS的全拼:concurrent mark sweep
    • A mostly concurrent , low-pause collector
    • Four phases: 
    1. initial mark (初始标记 STW开始标记)
    2. concurrent mark (并发标记和应用程序同时进行)
    3. remark (重新标记又是一个STW 在并发标记中产生的新垃圾 在这里进行重新标记 这里是使用多线程)
    4. concurrent sweep(并发清理的过程中也会产生新的垃圾 这个垃圾叫做浮动垃圾)

6.1、从线程角度理解:

垃圾回收器在工作的时候,垃圾回收的线程和工作线程同时进行,叫做:concurrent mark sweep;当内存比较小的情况下,清理垃圾的速度比较快没有问题,当内存越来越大较的时候,大到什么程度呢?大到你用多少线程进行清理的都需要很长一段时间,以前10G的内存的时候使用默认的ps+po大概需要的时间为11s。

 为什么会出现并发垃圾回收器?  并发垃圾回收器出现的原因是因为忍受不了STW.

6.2、下面来解释一下CMS常见的几个阶段:

第一个阶段叫做CMS initial mark(初始标记阶段)这个阶段很简单,就是直接找到最根上的对象,然后进行标记,其他的对象不标记。

第二个阶段是CMS concurrent mark(并发标记)据统计百分之八十的时间都浪费在这里,因此它把这块耗时最长的阶段和我们的应用程序同时进行,对于客户来说感觉上可能慢了点,但是至少还有反应,这里的并发标记是一边产生垃圾一边进行跟着标记,这个过程很难完成;

第三阶段是CMS remark (重新标记)这里又是一个STW,在上一个并发标记的过程中产生的新垃圾在这个阶段进行标记,这个时候需要停顿,但是时间不会很长,毕竟只是上一步很短时间内产生的新垃圾;

第四阶段是concurrent sweep(并发清理)并发清理也有他的问题,在并发清理的过程中也会产生新的垃圾,这个垃圾叫做浮动垃圾,这个浮动垃圾就要等下一次CMS来清理了;

什么条件下会触发CMS呢?老年代分配不下了,这时会触发CMS,这里的初始标记是单线程,重新标记是多线程。

6.3、CMS的缺点:CMS出现问题后会调用Serial Old使用单线程进行标记压缩;

 CMS的两大问题:

memory fragmentation 内存的碎片:这个是比比较严重的一个问题,如果内存超级大,产生了很多的碎片,这就会浪费很多的空间,其实CMS设计出来就是应付几百兆的内存至上G的内存,有的人拿它来应付很大内存就会出现问题,因为一旦老年代产生很多碎片,从新生代过来的对象就会出现找不到空间的情况,这叫做:PromotionFailed找不到空间。这时候它干了一件事情,把Serial Old 请出来,让它用一个线程在这里进行标记压缩。

floating garbage浮动垃圾:当出现Concurrent Mode Failure 和 PromotionFailed时,说明碎片较多,Old区内存分配不下,会调用Serial Old。并不是说使用了CMS之后这个问题没办法避免,可以降低触发CMS的阈值。

解决方法降低CMS的阈值:  -XX:CMSInitiatingOccupancyFraction 92%  可以降低这个值,让CMS保持老年代有足够的空间。

Remark阶段的算法:

怎么才能进行并发标记呢 非常的复杂,CMS采用的是三色标记+Incremental Update 算法。

      • 三色扫描算法:白灰黑
      • 在并发标记时,引用可能发生变化,白色对象有可能会被错误回收
      • 解决方法:SATB (snapshot at the beginning)     在起始的时候做一个快照    
      • Incremental Update  :  当一个白色对象被一个黑色对象引用时,将黑色对象重新标记为灰色,让垃圾回收器重新扫描;

常见的垃圾回收器就介绍这么多,下一篇会给大家介绍一下 PS+PO;如果写的有误的地方还请大佬指出

猜你喜欢

转载自blog.csdn.net/zhaofuqiangmycomm/article/details/113870362