当前位置: 首页 > ops >正文

垃圾收集器分类

垃圾收集器可以从不同维度分类:

  1. 按线程数

    • 串行(Serial):单线程执行垃圾收集。

    • 并行(Parallel):多线程并行执行垃圾收集。

  2. 按工作模式

    • 独占式:执行 GC 时,暂停所有应用线程(Stop-The-World, STW)。

    • 并发式:大部分 GC 工作与应用线程并发执行,只在某些阶段需要 STW。

  3. 按碎片处理

    • 压缩式:在回收后会对存活对象进行压缩整理,消除内存碎片。

    • 非压缩式:回收后不整理,会产生内存碎片。

    • 复制式:将存活对象复制到另一块内存区域,本身也是一种整理。


经典的垃圾收集器(JDK 8 及之前)

以下是 Java 8 及之前版本中经典的、可选的垃圾收集器,它们通常采用分代收集策略(将堆分为新生代和老年代)。

1. Serial 收集器(串行)

特点:最古老、最基础的单线程收集器。进行垃圾收集时,必须暂停所有工作线程(STW),直到收集结束。

适用区域:新生代(采用复制算法)、老年代(采用标记-整理算法)。

适用场景:客户端模式下的默认收集器。适用于内存资源受限、单核处理器或对停顿不敏感的场景(如桌面应用、小型应用)。

优点:简单高效,没有线程交互开销。

缺点:STW 时间较长。

2. Parallel Scavenge / Parallel Old 收集器(吞吐量优先)

特点:JDK 8 的默认收集器。关注点是可达到的吞吐量(吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间))。

新生代(Parallel Scavenge):多线程并行收集,使用复制算法

老年代(Parallel Old):多线程并行收集,使用标记-整理算法

适用场景:适合后台运算、科学计算、批量处理等不需要太多交互、追求高吞吐量的任务。

优点:吞吐量高。

缺点:STW 时间依然较长,不适合需要低延迟响应的应用。

3. ParNew 收集器

特点:本质是 Serial 收集器的多线程并行版本。除了使用多线程进行垃圾收集外,其余行为与 Serial 收集器完全一样。

适用区域:主要是新生代(采用复制算法)。

重要搭档:它是CMS 收集器在新生代的默认搭档。

适用场景:主要与 CMS 搭配使用,用于新生代的垃圾回收。

4. CMS(Concurrent Mark-Sweep)收集器(低延迟优先)

特点:以获取最短回收停顿时间为目标的收集器。大部分垃圾收集工作与用户线程并发执行。

适用区域:老年代(采用标记-清除算法,会产生内存碎片)。

执行过程(四个步骤)

  1. 初始标记(STW):标记 GC Roots 能直接关联到的对象。速度很快。

  2. 并发标记:从 GC Roots 开始进行可达性分析,与用户线程并发执行。

  3. 重新标记(STW):修正并发标记期间因用户程序继续运作而导致标记产生变动的那部分对象的标记记录。

  4. 并发清除:清理垃圾对象,与用户线程并发执行。

优点:并发收集,停顿时间短。

缺点

  1. 对 CPU 资源敏感,会占用一部分线程导致应用程序变慢。
  2. 无法处理“浮动垃圾”,可能在并发清理阶段产生新的垃圾。
  3. 使用标记-清除算法,会产生内存碎片,可能触发 Full GC。

5. G1(Garbage-First)收集器(全功能型)

特点:面向服务端应用的垃圾收集器,是 JDK 9 及以后的默认收集器。它试图取代 CMS。

革命性变化:它将堆内存划分为多个大小相等的独立区域(Region),虽然还保留新生代和老年代的概念,但它们都是Region的集合,不再是物理隔离。

核心思想:G1 跟踪各个 Region 里面的垃圾堆积的“价值”大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region(“Garbage-First”名字的由来)。

执行过程(四个步骤,与CMS类似但更先进)

  1. 初始标记(STW)

  2. 并发标记

  3. 最终标记(STW)

  4. 筛选回收(STW):根据用户期望的停顿时间来制定回收计划,将决定回收的 Region 中的存活对象复制到空的 Region 中,再清空整个旧的 Region。这是一个并行压缩的过程,有效避免了碎片。

优点

  1. 能充分利用多核CPU环境,缩短STW时间。

  2. 整体上看是标记-整理算法,局部(两个Region之间)看是复制算法,都不会产生内存碎片。

  3. 可预测的停顿:可以设置一个期望的停顿时间目标,G1会尽力达成。

如何选择垃圾收集器?

收集器目标适用场景JDK 默认情况
Serial简单高效,减少内存消耗单核CPU、客户端应用、嵌入式系统客户端模式默认
Parallel Scavenge/Old高吞吐量后台计算、批处理JDK 8 服务端模式默认
CMS低延迟Web 服务器、B/S 系统(已逐渐被淘汰)需手动启用
G1吞吐量与低延迟的平衡服务端应用,堆内存较大(6GB+)JDK 9+ 默认

选择建议:

  1. 如果不确定,使用默认值。从 JDK 9 开始,G1 是默认选择,它在大多数情况下表现良好。

  2. 如果应用追求高吞吐量(如数据处理),并且可以忍受较长的停顿,可以使用 -XX:+UseParallelGC

  3. 如果应用追求低延迟(如 Web 服务),堆内存较大(如超过 4-6G),选择 G1 -XX:+UseG1GC

http://www.xdnf.cn/news/20250.html

相关文章:

  • 「数据获取」《中国电力统计年鉴》(1993-2024)(含中国电力年鉴)
  • 分布式数据库的历史演变与核心原理
  • SpringBoot配置文件
  • 【CSP-S】数据结构 ST 表详解
  • 植物大战僵尸融合版安装包,下载安装教程
  • PCDN工作原理的详细步骤
  • Netty从0到1系列之EventLoopGroup
  • Kafka面试精讲 Day 10:事务机制与幂等性保证
  • CUDA默认流的同步行为
  • 项目升级--kafka消息队列的应用
  • 状压 dp --- 数据范围小
  • 雪球科技Java开发工程师笔试题
  • happen-before原则
  • WSL Ubuntu Docker 代理自动配置教程
  • LeetCode 139. 单词拆分 - 动态规划解法详解
  • 【软考架构】第二章 计算机系统基础知识:计算机网络
  • 主数据系统是否对于企业是必需的?
  • 最大似然估计:损失函数的底层数学原理
  • 基本数据类型和包装类的区别?
  • 2025年大数据专业人士认证发展路径分析
  • MySQL运维补充
  • 【目录-判断】鸿蒙HarmonyOS开发者基础
  • 敏捷scrum管理实战经验总结
  • 贪心算法应用:化工反应器调度问题详解
  • 【LLIE专题】SIED:看穿0.0001lux的极致黑暗
  • NPU边缘推理识物系统
  • 懒加载的概念
  • 新能源风口正劲,“充电第一股”能链智电为何掉队?
  • 操作系统启动过程详解
  • Coze源码分析-资源库-删除插件-前端源码-核心组件实现