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

深入剖析 JVM 垃圾收集器之 CMS 和 G1

在 Java 虚拟机(JVM)的世界里,垃圾收集器是一个至关重要的组件,它负责自动回收不再被使用的内存空间,保证应用程序的稳定运行。本文将着重介绍两种具有代表性的垃圾收集器:CMS(Concurrent Mark Sweep)收集器和 G1(Garbage-First)收集器。

CMS 收集器

基本原理

CMS 收集器是一种以获取最短回收停顿时间为目标的收集器。它的工作过程主要分为以下几个阶段:

  1. 初始标记(Initial Mark): 暂停所有的应用线程,标记出所有 GC Roots 能直接关联到的对象。这个阶段速度很快,但会导致应用短暂停顿。
  2. 并发标记(Concurrent Mark): 与应用程序线程并发执行,从 GC Roots 的直接关联对象开始遍历整个对象图,标记出所有可达对象。这个阶段不会停顿应用线程,但耗时较长。
  3. 重新标记(Remark): 暂停应用线程,修正并发标记期间因应用程序继续运行而导致标记产生变动的那一部分对象的标记记录。停顿时间比初始标记稍长,但远比并发标记短。
  4. 并发清除(Concurrent Sweep): 与应用程序线程并发执行,清除掉标记为不可达的对象所占用的内存空间。

特点

  • 优点:并发收集、低停顿,能较好地满足对响应时间要求较高的应用场景。
  • 缺点
    • 对 CPU 资源非常敏感,在并发阶段会占用一部分 CPU 资源,导致应用程序性能下降。
    • 无法处理浮动垃圾(Floating Garbage),可能出现 “Concurrent Mode Failure” 失败进而触发 Full GC。
    • 采用标记 - 清除算法,会产生内存碎片,当碎片过多时,可能会提前触发 Full GC。

适用场景

适用于注重响应时间,并且应用程序运行过程中产生的垃圾对象不是特别多的场景,比如互联网电商的交易系统、在线支付系统等。

G1 收集器

基本原理

G1 收集器是一种面向服务器的垃圾收集器,它将整个 Java 堆划分为多个大小相等的独立区域(Region),并跟踪各个 Region 里面的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的 Region。它的工作过程主要包括:

  1. 初始标记(Initial Mark): 暂停应用线程,标记出 GC Roots 能直接关联到的对象,并且修改 TAMS(Top at Mark Start)的值,让下一阶段用户程序并发运行时,能正确地在可用的 Region 中分配新对象。
  2. 并发标记(Concurrent Mark): 与应用程序线程并发执行,从 GC Roots 开始对堆中对象进行可达性分析,标记出所有可达对象。
  3. 最终标记(Final Mark): 暂停应用线程,处理并发标记阶段结束后仍遗留下来的少量 SATB(Snapshot-At-The-Beginning)记录。
  4. 筛选回收(Live Data Counting and Evacuation): 首先对各个 Region 中的存活对象进行统计,然后根据用户期望的停顿时间来制定回收计划,回收价值最大的 Region(这些 Region 中包含的垃圾对象最多)。回收过程中采用复制算法,将一个 Region 中的存活对象复制到另一个 Region 中,从而避免了内存碎片的产生。

特点

  • 优点
    • 并行与并发:G1 能充分利用多 CPU、多核环境下的硬件优势,使用多个 CPU 来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 Java 程序继续执行。
    • 分代收集:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次 GC 的旧对象,这仍然是一种分代的概念。
    • 空间整合:G1 从整体来看是基于 “标记 - 整理” 算法实现的收集器,从局部(两个 Region 之间)上来看是基于 “复制” 算法实现的,这两种算法都意味着 G1 运行期间不会产生内存碎片,垃圾收集完成之后能提供规整的可用内存。
    • 可预测的停顿:G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒。
  • 缺点
    • 相比其他垃圾收集器,G1 在垃圾回收过程中产生的内存占用(Footprint)和程序运行时的额外执行负载(Overload)可能会高一些。
    • 由于 G1 的算法较为复杂,在实现和调优方面对开发者的要求相对较高。

适用场景

适用于大内存、多核 CPU 的服务器环境,并且应用程序对停顿时间有比较严格要求的场景,如大规模的电商平台、金融交易系统等。

CMS 与 G1 收集器对比

  1. 停顿时间:CMS 以获取最短回收停顿时间为目标,但在高并发情况下可能出现较长停顿;G1 能建立可预测的停顿时间模型,在大内存情况下,停顿时间通常比 CMS 更可控。
  2. 内存管理:CMS 采用标记 - 清除算法,容易产生内存碎片;G1 采用标记 - 整理和复制算法,避免了内存碎片问题。
  3. CPU 资源占用:CMS 在并发阶段对 CPU 资源非常敏感,会影响应用程序性能;G1 虽然也会占用一定 CPU 资源,但由于其并行和并发的特点,在多核环境下能更好地利用 CPU 资源。
  4. 适用场景:CMS 适用于响应时间要求高、垃圾产生量相对较少的场景;G1 适用于大内存、对停顿时间有严格要求的场景。

CMS 和 G1 收集器都有各自的特点和适用场景,在实际应用中,我们需要根据应用程序的特点和需求来选择合适的垃圾收集器,以达到最佳的性能表现。同时,随着 JVM 技术的不断发展,垃圾收集器也在持续演进,未来有望出现更高效、更智能的垃圾收集器。


http://www.kler.cn/a/538385.html

相关文章:

  • DeepSeek 评价开源框架存在幻觉么?
  • 如何搭建DeepSeek R1的训推环境?
  • Python Pandas(5):Pandas Excel 文件操作
  • Centos执行yum命令报错
  • GnuTLS: 在 pull 函数中出错。 无法建立 SSL 连接。
  • RabbitMQ 从入门到精通:从工作模式到集群部署实战(五)
  • Golang:精通sync/atomic 包的Atomic 操作
  • 本地计算机上的MySQL80服务启动后停止某些服务在未由其他服务或程序使用时将自动停止(不需要清除数据)
  • 今日写题work
  • Https握手过程 (面试题)
  • PMP–一、二、三模–分类–13.干系人管理
  • Python关键字全解析与实例应用
  • python Excel 表读取合并单元格以及清除空格符
  • #渗透测试#批量漏洞挖掘#微商城系统 goods SQL注入漏洞
  • JUnit 5 中获取测试类、测试方法及属性的注解
  • DeepSeek与Vue.js组件开发:解锁AI与前端开发的融合密码
  • 算法兵法全略(译文)
  • 低代码系统-插件功能分析( 某道云)
  • 线性dp-安全序列
  • 指向深度学习的“信息技术”课程单元教学设计方案
  • 数据表中的视图操作
  • 激活函数篇 03 —— ReLU、LeakyReLU、RandomizedLeakkyReLU、PReLU、ELU
  • 如何参与开源项目
  • 33.日常算法
  • Python进阶-在Ubuntu上部署Flask应用
  • iPhone 在华销量大幅下挫