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

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.分代收集 & 垃圾收集器)