jvm gc小结

2020-02-02  本文已影响0人  wyfwo
image.png

注:图中有连线相连的,表示可以搭配使用,如新生代ParNew + 老年代CMS。

YoungGC = MinorGC:对新生代进行回收,在Eden区满的时候触发;

FullGC:新生代+老年代同时回收,即对整个堆进行回收,老年代满了会触发。

1、新生代收集器(Eden + S0 + S1,标记复制)

  1. Serial

    1. 单线程版本,只有一个gc线程;

    2. gc线程与用户线程串行执行,STW;

    3. 适用于:client模式下,虚拟机内存分配不大、单cpu环境时,减少切换开销,高效执行回收;

  2. ParNew

    1. 多线程版本的serial收集器,策略等完全一样;

    2. 多个gc线程并行回收,专注于减少STW时长,提升响应速度;

    3. 更适合用于,与用户交互的程序;stw越短体验越好

  3. Parallel Scavenge

    1. 多gc线程并行收集

    2. 自适应策略,自动调节新老代大小比例等参数,专注于可控制的吞吐量(吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间))

    3. 更适用于非用户交互的后台计算程序等;

2、老年代收集器

  1. Serial old

    1. Serial 收集器的老年代版本;

    2. 适用于client模式下的老年代收集;

    3. 作为CMS收集器的后备预案,在并发收集发射Concurrent Mode Failure时使用; image.png
  2. Parallel Old

    1. Parallel Scavenge 的老年代版本;

    2. 多线程 + 标记整理算法;

    3. 与Parallel Scavenge(新生代回收)组合,实现【吞吐量优先】目标;

      image.png
  3. CMS

    1. 以实现最短STW时间为目的,适用于注重响应速度、用户体验的服务;

    2. 主要步骤: image.png
      1. 初始标记:仅标记GC Roots能够关联的对象,STW时间很短;

      2. 并发标记:与用户线程并发执行,无STW,用于GC Roots Tracing的分析过程,耗时较长;

      3. 重新标记:用于修正并发标记期间由于用户线程同时执行导致标记变动的记录,STW时间较短,但比初始标记长;

      4. 并发清除:与用户线程同时进行,清除标记的垃圾;

    3. 存在的问题:

      1. 采用标记清除算法,产生碎片,导致频繁的FullGC,可以设置-XX:+UseCMSCompactAtFullCollection(默认开启),在FullGC时进行内存碎片整理;可以设置-XX:CMSFullGCsBeforeCompaction,标识执行多少次不带压缩的FullGC后执行一次带压缩的;

      2. 对cpu资源敏感,gc线程占用cpu资源导致吞吐量下降。默认启动线程数是 (CPU数量 + 3)/4,如果只有一两个cpu,则吞吐量将下降50%!!!

      3. 易产生“浮动垃圾”:由于并发清除阶段,用户线程在并发执行产生的新的垃圾得不到及时回收;用户线程的执行也需要预留足够的空间,如预留空间不够,则会出现Concurrent Mode Failure,只能使用Serial old收集器重新收集,导致STW更长!!!

  4. G1(Garbage First)

    1. 多线程可以与用户线程并发执行;

    2. 不会产生碎片:基于region的设计,整体采用标记整理算法,局部两个region之间基于复制算法实现; image.png
    3. 可控可预测的STW时间:记录维护各个region的回收价值,优先收集回收价值高的region(只回收部分region,避免回收整个老年代)

    4. 主要步骤: image.png
      1. 初始标记:类比CMS

      2. 并发标记:类比CMS

      3. 最终标记:类比CMS

      4. 筛选回收:不同于CMS,根据用户设定的允许收集时长,选取部分高回收价值的region,优先收集。

        1. 避免FullGC,可控STW时间

        2. 不牺牲吞吐性能

        3. 不会产生内存碎片,有利于长期运行;

上一篇下一篇

猜你喜欢

热点阅读