JVM-垃圾回收器

JVM——垃圾回收器

1. 垃圾回收器分类

分类标准:串行/并行、并发/独占、压缩式/非压缩式、年轻代/老年代

2. 回收器评价标准

  • 吞吐量:$\frac{t_{运行用户代码}}{t_{运行用户代码} + t_{垃圾回收}}$,即尽可能让单位时间内的STW时间最短
  • 暂停时间:尽可能让单次STW时间最短

3. Serial回收器

Serial 收集器

串行;年轻代为Serial(标记-复制算法),老年代为Serial Old(标记-整理算法)

4. ParNew回收器

ParNew 收集器

并行;只能用于年轻代(标记-复制算法),老年代仍为Serial-Old

5. Parallel Scavenge回收器

Parallel Old收集器运行示意图

并行;关注吞吐量;年轻代为Parallel Scavenge(标记-复制算法),老年代为Parallel Old(标记-整理算法)

6. CMS回收器(Concurrent-Mark-Sweep)

CMS 收集器

并发;只能用于老年代,但无法与Parallel Scavenge一起使用

CMS回收器收集流程

  1. 初始标记:只标记出与GCRoots直接关联的对象,会发生STW但时间短
  2. 并发标记:从上面得到的与GCRoots直接关联的对象开始遍历标记,可与工作线程并发执行,无需STW
  3. 重新标记:修正并发标记过程中,由于用户程序继续运行导致标记产生变动的一部分对象的标记记录,会产生STW但时间也不长
  4. 并发清除:删除标记阶段判断死亡的对象,由于没移动对象(标记-清除),故可以与用户线程并发执行
  • 优点:并发;低延迟
  • 缺点:
    • 由于采用的是标记-清除算法,会产生内存碎片
    • 会产生**“浮动垃圾”**:由于并发清除阶段是与工作线程并发执行的,这期间产生的垃圾要等到下次gc次才能清除

CMS回收器的兜底策略

CMS 最大的弱点在于它使用的是标记-清除(Mark-Sweep)算法,这会产生大量的内存碎片。

  • 触发场景:
    1. 并发失败(Concurrent Mode Failure): 当 CMS 还在进行并发回收时,老年代的剩余空间已经不足以支撑新对象的分配(或者是从年轻代晋升过来的对象)。
    2. 晋升失败(Promotion Failed): 虽然老年代总空闲空间够,但由于碎片化太严重,找不到一块连续的空间来存放晋升的大对象。
  • 兜底操作:
    • Serial Old GC: CMS 会立即停止所有工作,切换到单线程的 Serial Old 收集器
    • 全堆压缩: 这是一个极重的操作,它会进行全堆扫描并进行内存压缩(Compaction)以消除碎片。
  • 后果: 产生一个非常漫长的 STW 停顿,在几十 GB 的堆内存上,这可能会导致应用“假死”数秒甚至数分钟。

7. G1回收器(Garbage First)

G1 收集器

G1回收器将堆内存分割为许多个小区域region,G1跟踪各个region里垃圾堆积价值大小(回收获得空间大小 以及 回收所需时间的经验值),在后台维护一个优先列表,每次根据允许时间,优先回收价值最大的region

G1回收器收集流程:

  1. 初始标记
  2. 并发标记
  3. 重新标记
  4. 筛选回收:制定回收计划,选择多个region作为回收集,把回收集中存活对象复制到空的region中,再清理旧region中的全部空间,需要STW

G1 的兜底策略

G1 采用的是分代/分区(Region)算法,虽然它比 CMS 更智能,但依然有极限。

  • 触发场景:
    1. 转移失败(Evacuation Failure): G1 在将存活对象从一个 Region 复制到另一个 Region(To-Space)时,发现没有可用的空闲 Region 了。
    2. 并发模式失败(Concurrent Mode Failure): 在并发标记完成前,堆内存就已经被填满。
    3. 巨型对象分配失败: 当大对象请求分配,但连续的空闲 Region 数量不足时。
  • 兜底操作:
    • Full GC: 触发一次全堆范围的 STW 回收。
    • 版本差异:
      • JDK 8 及以前: G1 的 Full GC 是单线程的,性能非常差。
      • JDK 10 及以后: G1 的 Full GC 得到了优化,改为并行(Parallel Full GC),利用多核 CPU 加快清理速度。
  • 后果: 虽然在现代 JDK 中由于是多线程并行清理,速度比 CMS 的单线程兜底快不少,但依然属于“重度卡顿”。

8. CMS G1垃圾回收器的三色标记是什么?

三色标记是用于垃圾回收的标记算法,CMS 和 G1 垃圾回收器都有采用。它将对象分为三种颜色:

  • 白色:初始状态,代表尚未被垃圾回收器访问的对象。标记结束仍为白色的对象,意味着未被程序引用,会被当作垃圾回收。

  • 灰色:表示对象已被访问,但它引用的其他对象还没全被访问,处于“中间状态”。

  • 黑色:对象及其引用的所有对象都已被访问过。黑色对象在本轮标记中不会被回收。

三色标记能在并发标记时,和用户线程并发执行,提高效率,但可能产生浮动垃圾和对象消失问题。


JVM-垃圾回收器
http://example.com/2025/05/16/JVM-垃圾回收器/
作者
Kon4tsu
发布于
2025年5月16日
许可协议