美文网首页
JVM的GC算法

JVM的GC算法

作者: 掩流年 | 来源:发表于2020-03-11 23:34 被阅读0次

    GC分代假说

    我们都知道,绝大多数对象都是朝生夕死。对于绝大多数GC算法而言都会遵循基本的分代假设。
    它的结构如下所示,即


    分代假说
    Young

    此区域使用的GC算法为Mark and Copy,即没被回收的对象会被标记出来然后拷贝到幸存区。

    • Eden(TLAB 线程私有的分配缓存区,加快分配速度)
    • Survivor1
    • Survivor2


      年轻代

      在年轻代,会触发Minor GC,年轻代的垃圾回收能回收掉70%--90%的内存。而幸存的对象会进入Survivor区中,并且每次Minor GC触发,不会被回收的对象会在Survivor区中交替复制,直到次数大于15次,这些对象会进入老年代。

    Tenured(Old)

    在老年代,使用的GC算法是Mark-Sweep-Compact,即没被回收的对象,会被标记出来,然后为了减少内存碎片,尽量的压缩成一块区域。
    在老年代调用的使用的是Major GC区回收

    PermGen/Metaspace

    GC收集器

    GC Mark
    • Stop The World (STW)
      在GC开始之前,会先进行标记。标记的时候,要先把进程停止掉。所有的GC在工作的过程中,都要涉及到或多或少的STW,这是程序卡顿的原因。也是我们经常调优的目标。
    • safe point
      当GC触发之前,先要运行到一个安全点,才能进行STW,通常而言,GC的停顿与堆大小无关,而是与活对象的大小有关。增加堆大小有时候反而会增加延迟。

    我们下面介绍的垃圾回收器有三种SerialParallelCMSG1

    垃圾收集算法
    Serial

    serial回收算法如上图,分别应用在年轻代和老年代。基本和分代假说的说法一样,一根线程,从年轻代的标记复制,到STW,到老年代的标记清除整理。

    Parallel

    串行回收的并发版本,所作的事情是一样的。
    我们可以从上图中看到的是,Parallel有三个回收器,即ParNew,Parallel Old,Parallel Scavenge,其中Parallel OldParallel Scavenge是搭配使用的。至于ParNew是因为CMS回收器只能回收老年代,它被开发出来用于和CMS搭配使用,回收年轻代。

    CMS
    GC回收算法对比

    我们可以看到左边是一个串行收集器,右边是CMS收集器,这两个对比起来,CMS的STW过程Initial Mark是一个比较短暂的过程,然后标记过程会和用户线程一起去执行,但是可能执行标记的不准确, 所以在之后的一段时间,又STW一会,并发去Remark标记。之后在清除的过程中,和用户线程并发的执行。

    并且在CMS中,老年代只进行Mark-Sweep,而不进行Compact,主要用于低延时的系统。

    G1

    G1在Java9之后成为了默认的GC。如果想在Java8中使用它,可以加个参数Use G1 GC。

    它横跨了年轻代和老年代,它制定的目标是软实时,比较大的堆内存(大于4G),可以设定目标(设定停顿时间,尽量达到)。

    在G1的设计中,没有分代假说的存在了。它会将堆分成若干个等大的区域。


    G1

    再回收的时候无需回收整个堆,而是回收一个Collection Set,即一个区域的集合。
    在GC1中,有两种GC:

    • Fully young GC
    • Mixed GC
      估计每个Region中的垃圾比例,优先回收垃圾多的Region。

    相关文章

      网友评论

          本文标题:JVM的GC算法

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