美文网首页JVMjava面试
【JVM-垃圾收集】1.分代收集 & 垃圾收集器

【JVM-垃圾收集】1.分代收集 & 垃圾收集器

作者: bit_拳倾天下 | 来源:发表于2022-07-06 21:10 被阅读0次

    0. 分代收集

    当前大多数商业虚拟机的垃圾收集器都遵循“分代收集”。就是针对不同的内存区域使用不同的数计算法。但是已经有能够全区域收集不分代的收集器了。因为不同的区域有不同的特点,为是各个区域达到最好的效果,所以进行分代。
    未来会不会不分代的虚拟机主导呢,真是的,@_@学习的速度赶不上技术发展的速度。。。听说隔壁 Rust 已经不用垃圾收集了!!

    • 部分收集(Partial GC):不是针对完整的 java 堆的垃圾收集
      • 新生代收集(Minor GC / Young GC):只针对新生代的垃圾收集
      • 老年代收集(Major GC / Old GC):只针对老年代的垃圾收集
      • 混合收集(Mixed GC):针对整个新生代 + 部分老年代的垃圾收集
    • 整堆收集(Full GC):针对整个 java 堆区的垃圾收集,包括新生代、老年代、方法区

    0.1 新生代收集(Minor GC / Young GC)

    只针对新生代的垃圾收集
    触发条件:
    Eden 满了或不够分配对象了,survivor 满了不会触发,会等到Eden 满了一起收集。

    细节
    MinorGC 有个细节,就是 MinorGC 之前,会做一次检查,检验 老年代的最大连续空间 是否大于 新生代所有对象的总和。如果大于,则说明 MinorGC 是安全的,进行 MinorGC;否则就直接进行 FullGC。另外空间担保策略(-XX:HandlePromotionFailure)在 jdk7 之后已经失效了。

    回收过程简图

    正常情况下,是 GC 年龄达到阈值后会移动到老年代,但是有两种特殊情况:

    1. 大对象,Eden 区放不下的情况下,会进行一次 youngGC,如果 GC 之后还放不下就直接进入老年代;或者 Eden 区的幸存者,survivor 区存不下,也会直接晋升到老年代
    2. 当同一年龄的对象总和大于 survivor 的一般时,大于等于该年龄的对象就会直接进入老年代,而不用等到阈值年龄

    特点:

    1. 频率较高
      程序运行过程中会持续创建对象,且大多数对象都是使用一次就结束了,所以新生代收集比较频繁
    2. 速度快
      占用内存较小,另外复制算法效率也较高
    3. stop the world
      垃圾收集期间,会暂停用户线程,等垃圾回收结束在回复用户线程,但是因为回收速度较快,所以影响较小

    0.2 老年代收集(Major GC / Old GC)

    只针对老年代的垃圾收集,目前只有 CMS 有单独收集老年代的行为

    1. stop the world
    2. 速度缓慢,是 minorGC 的 10 倍以上
    3. MajorGC 后空间还不足,则 OOM

    很多时候会和 FullGC 混淆,需要具体问题具体分析

    0.3 混合收集(Mixed GC)

    针对整个新生代 + 部分老年代的垃圾收集,目前只有 G1 收集器有混合收集

    0.4 整堆收集(Full GC)

    针对整个 java 堆区的垃圾收集,包括新生代、老年代、方法区
    触发条件:

    1. System.gc()
    2. 老年代空间不足
    3. 方法去不足
    4. minorGC 判定为幸存的、要移动到老年代的对象大于老年代可用空间
    5. eden 区的幸存者,survivor 存放不下,需要移动到老年代,但是可用空间不足

    fullGC 是尽量要避免的,下图是对象分配和 GC 的简图


    1. 垃圾收集器

    常用垃圾收集器
    1. Serial + Serial Old
      较早的垃圾收集器组合,垃圾收集是单线程完成,用于早期应用程序小、内存占用小的时期。
      GC 期间会停止用户线程,俗称 stop the world(stw)

    适用场景:适用于服务器性能差的情况,例如服务器只有 2 核

    1. Parallel Scanvege + Parallel Old
      随着应用程序体量的增加,内存占用原来越大,单线程收集垃圾缓慢,伴随着更长的 stw,所以出现了多线程收集器,Parallel + Parallel Old 就是多线程 GC 的收集器组合,同时也是 jdk8 默认的收集器
      GC 期间也会 stw。

    适用场景:注重吞吐量的场景

    1. CMS + ParNew(Parallel Scanvege 的增强版)
      多线程 GC 虽然降低了收集时间,但仍然存在 stw,于是诞生了 Concurrent 的收集器,用户线程和 GC 线程可以并发执行。CMS 就是这类收集器的最早实践者。

    并发收集包括以下几个阶段

    1. 初始标记
      stw
    2. 并发标记
      三色标记算法待补充
    3. 重新标记
      stw
    4. 并发清理

    适用场景:与 G1 类似,注重低延迟的情况

    1. G1、ZGC、Shenandoah
      都是并发收集

    相关文章

      网友评论

        本文标题:【JVM-垃圾收集】1.分代收集 & 垃圾收集器

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