美文网首页
JVM系列之GC垃圾收集器

JVM系列之GC垃圾收集器

作者: 简楼 | 来源:发表于2021-04-07 21:12 被阅读0次

    前言

    JVM中GC垃圾回收算法我们已经了解了,那么现在,我们能区分哪些是JVM中的垃圾了,知道他们该回收了;

    那么现在就差一个垃圾篓了,用来收集垃圾,然后统一销毁,这就是我们今天要学习的GC垃圾收集器;

    GC垃圾收集器(以HotSpot为例)

    HotSpot虚拟机提供了7种垃圾收集器,适用于新生代的三种,老年代的三种,还有一种新生代老年代都适用。

    新生代垃圾收集器:Serial收集器,ParNew收集器,Parallel Scavenge收集器

    老年代垃圾收集器:Serial Old收集器,Parallel Old收集器,CMS收集器

    新老适用的收集器:G1收集器

    垃圾收集器使用区域情况.png

    Serial 收集器

    Serial收集器曾是jdk1.3之前新生代收集器的唯一选择,串行收集器,单线程工作,所以效率高,但是会产生Stop The World,适用于堆内存比较小的时候使用,使用复制算法回收垃圾对象

    参数设置:-XX:+UseSerialGC 使用Serial收集器

    Serial Old 收集器

    Serial Old收集器是Serial的老年代版本,单线程收集器,使用标记整理算法;

    可以与Parallel Scavenge收集器搭配使用,也可以作为CMS收集器发生Concurrent Mode Failure时老年代的备选方案使用;

    image.png

    ParNew 收集器

    parNew收集器是Serial收集器的多线程版本,并行收集器,除了多线程收集外,其余功能与Serial收集器基本一致,在新生代中,除了Serial收集器,只有ParNew收集器可以与CMS收集器一起使用,所以目前为止这个收集器是新生代最常用的收集器


    image.png

    参数设置:

    • -XX:+UseParNewGC:使用ParNew收集器
    • -XX:ParallelGCThreads:用来限制垃圾收集的线程数

    Parallel Scavenge 收集器

    并行收集器,使用复制算法,与其余两种年轻代收集器不同的地方,Serial和ParNew收集器在于尽可能的缩短Stop The World的时间,而Parallel Scavenge收集器的关注点在于吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间));

    参数设置:

    • -XX:+UseParallelGC:使用Parallel收集器
    • -XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间
    • -XX:GCTimeRatio:设置吞吐量大小,默认为99,允许1%的垃圾收集时间
    • -XX:+UseAdaptiveSizePolicy:自适应调节,设置之后就不需要手动设置新生代大小

    Parallel Old 收集器

    Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用标记整理算法;

    在注重吞吐量及CPU资源敏感的场景,可以用考虑使用Parallel Scavenge+Parallel Old收集器;

    参数设置:

    • -XX:+UseParallelOldGC:使用Parallel Scavenge + Parallel Old收集器
    image.png

    CMS收集器

    CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,目前使用最多的垃圾收集器,使用这类收集器的应用重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验;

    使用标记清除算法,共4个步骤

    1. 初始标记(CMS initial mark)
    2. 并发标记(CMS concurrent mark)
    3. 重新标记(CMS remark)
    4. 并发清除(CMS concurrent sweep)

    初始标记、重新标记这两个步骤仍然需要Stop The World,初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短
    耗时较长的并发标记和并发清除的线程可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发地执行;

    优点:并发收集,低停顿;
    缺点:

    1. 对CPU资源敏感
      CMS默认启动的回收线程数量是(CPU数量+3)/4,当CPU数量小于4时,并发操作时会占用一半的CPU去进行垃圾收集

    2. 无法处理浮动垃圾,可能回导致Concurrent Mode Failure失败而导致领一次Full GC的产生
      CMS收集器触发GC时需要预留一部分空间供并发收集时使用,通过设置参数-XX:CMSInitiatingOccupancyFraction的值来提高触发的百分比
      当预留的空间无法满足需求时就会发生Concurrent Mode Failure失败,这时,java虚拟机就会采用Serial Old收集器回收老年代垃圾,代价就是停顿时间变长
      所以-XX:CMSInitiatingOccupancyFraction参数设置的过高容易频繁触发Concurrent Mode Failure失败,导致性能降低

    3. 产生大量空间碎片
      设置-XX:+ UseCMSCompactAtFullCollection参数,开启空间压碎,默认是开启的,开启后FUll GC时会进行内存整理,空间碎片问题解决,但是停顿时间就会变长
      设置-XX:+ CMSFullGCsBeforeCompaction参数,设置进行几次Full GC后,进行一次碎片整理,默认是0,表示每次进入Full GC时都进行碎片整理


      image.png

      参数设置:

    • -XX:+UseConcMarkSweepGC:使用CMS收集器 + PerNew收集器
    • -XX:ParallelCMSThreads:设定CMS的线程数量

    G1 收集器

    G1是一款面向服务端应用的垃圾收集器,HotSpot开发团队赋予它的使命是未来可以替换掉JDK1.5中发布的CMS收集器;

    G1收集器将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔阂了,它们都是一部分(可以不连续)Region的集合;

    G1的新生代收集跟ParNew类似,当新生代占用达到一定比例的时候,开始出发收集;和CMS类似,G1收集器收集老年代对象会有短暂停顿;

    G1收集器采用标记整理算法,所以G1收集器不会产生空间碎片;

    G1特点:

    • 并行与并发:G1可以充分的利用多CPU和多核环境下的硬件优势用来缩短Stop The World的停顿时间
    • 可预测的停顿:降低停顿时间是G1和CMS的共同关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为N毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。

    收集步骤:

    1. 初始标记:标记一下GC Roots能直接关联到的对象
    2. 并发标记:从GC Roots出发,开始对堆中对象进行可达性分析,找出存活对象
    3. 最终标记:为了修正并发标记阶段因用户程序继续运行而导致标记产生变动的那一部分标记记录
    4. 筛选回收:对各个Region的回收价值和成本进行排序,根据用户所期待的GC停顿时间来制定回收计划
    image.png

    相关文章

      网友评论

          本文标题:JVM系列之GC垃圾收集器

          本文链接:https://www.haomeiwen.com/subject/toqpkltx.html