Java 的 CMS 垃圾回收流程

CMS(Concurrent Mark-Sweep)垃圾回收器 是一种并发垃圾回收器,旨在减少垃圾回收时的停顿时间,适用于对低延迟要求较高的应用。CMS 主要通过并发标记和并发清除阶段来减少暂停时间。CMS 主要包含以下几个阶段:


1. CMS 的垃圾回收流程

CMS 的垃圾回收过程包括以下几个阶段:

1.1 初始标记(Initial Mark)

  • 触发条件:在进行标记之前,首先需要执行初始标记阶段。
  • 过程
    • 停止应用线程(STW)。
    • 标记根对象(GC Roots)直接可达的对象。
    • 这一步骤只标记 GC Roots 引用的对象,不会遍历整个堆,时间较短。

1.2 并发标记(Concurrent Mark)

  • 触发条件:初始标记完成后,进入并发标记阶段。
  • 过程
    • 这一阶段与应用线程并发进行,即垃圾回收线程和应用线程同时执行。
    • 从根对象出发,扫描堆中所有的对象,标记所有可达对象。
    • 由于并发执行,标记过程中对象的引用可能发生变化,但 CMS 会通过 写屏障 机制来记录对象的引用变化。
    • 该阶段的时间较长,但由于与应用线程并发执行,所以不需要额外的 STW 时间。

1.3 重新标记(Remark)

  • 触发条件:并发标记阶段完成后,进入重新标记阶段。
  • 过程
    • 停止应用线程(STW)。
    • 通过扫描和处理并发标记期间的引用变化,修正并发标记时遗漏的引用。
    • 由于这一步涉及到修正标记图,因此需要暂停应用线程,时间比初始标记略长。

1.4 并发清理(Concurrent Sweep)

  • 触发条件:重新标记阶段完成后,进入并发清理阶段。
  • 过程
    • 这一阶段与应用线程并发进行。
    • 垃圾回收器扫描整个堆,清除未被标记的对象(即垃圾对象)。
    • 由于并发执行,该过程不会影响应用程序的运行。

1.5 并发重置(Concurrent Reset)

  • 触发条件:清理阶段完成后,准备进行下一次垃圾回收。
  • 过程
    • 重置内部的数据结构,为下一次垃圾回收做准备。
    • 这通常是一个非常短的阶段,可能会与应用线程并发执行。

2. CMS 垃圾回收流程的关键点

2.1 写屏障(Write Barrier)

  • 为了保证并发标记的准确性,CMS 使用了写屏障。当应用线程修改对象引用时,写屏障会记录修改,确保这些修改能够被垃圾回收器捕捉并标记。
  • 例如,在并发标记阶段,如果对象引用发生变化,写屏障会将相关的变化记录到“记忆集”中,以便后续在重新标记阶段处理。

2.2 记忆集(Remembered Set)

  • 记忆集是用于记录跨代引用的集合。由于 CMS 采用的是分代垃圾回收机制,跨代引用(即从年轻代到老年代的引用)会通过记忆集来跟踪,确保标记过程不漏掉跨代引用。

3. CMS 的优缺点

优点:

  1. 低停顿时间:通过并发标记和并发清理,CMS 将大部分工作与应用线程并行执行,减少了 STW 的停顿时间。
  2. 较短的垃圾回收暂停:特别适合对响应时间要求高的应用程序,如金融、电商等领域。
  3. 适应大堆内存:CMS 可在堆内存较大的情况下保持较低的停顿时间。

缺点:

  1. 垃圾回收效率较低:虽然并发进行,但仍有清理过程需要耗费较长时间,尤其在老年代垃圾量较多时,可能出现停顿时间较长的问题。
  2. 可能发生 Concurrent Mode Failure(并发模式失败):如果老年代空间不足,无法为新对象分配内存,CMS 会触发 Full GC,导致全停顿,影响应用性能。
  3. 内存碎片:由于 CMS 使用的是标记-清除算法,可能会导致老年代内存碎片化,从而降低内存的利用率。

4. CMS 与其他垃圾回收器的对比

4.1 与 Serial GC 对比

  • Serial GC 是一个单线程的垃圾回收器,所有的回收操作都需要停顿应用程序。
  • 相比之下,CMS 采用并发标记和清理的方式,可以减少停顿时间,适合需要低延迟的应用。

4.2 与 G1 对比

  • G1 是一个区域化的垃圾回收器,可以更精细地控制回收过程,通过并发标记、清理以及分代回收,优化停顿时间。
  • CMS 更倾向于老年代的清理,而 G1 在处理混合垃圾回收时会优先回收高垃圾比例的区域,更加灵活。

5. 总结

CMS 垃圾回收器采用并发标记和并发清理的方式,显著降低了垃圾回收的停顿时间。其主要流程包括:

  1. 初始标记:标记 GC Roots 可达对象。
  2. 并发标记:与应用线程并发进行,标记所有可达对象。
  3. 重新标记:处理并发标记期间的引用变化。
  4. 并发清理:与应用线程并发清理垃圾对象。

CMS 的设计旨在减少停顿时间,但也存在可能出现内存碎片和并发模式失败的问题。对于要求低延迟的应用,CMS 是一个理想的选择,但对于大堆内存应用,可能需要更强大的 G1 回收器来替代。

Java 的 CMS 垃圾回收流程的更多相关文章

  1. Java编程思想学习笔记_1(Java内存和垃圾回收)

    1.Java中对象的存储数据的地方: 共有五个不同的地方可以存储数据. 1)寄存器.最快,因为位于处理器的内部,寄存器按需求分配,不能直接控制. 2)堆栈.位于通用RAM,通过堆栈指针可以从处理器那里 ...

  2. CMS垃圾回收机制

    详解CMS垃圾回收机制   原创不易,未经允许,不得转载~~~ 什么是CMS? Concurrent Mark Sweep. 看名字就知道,CMS是一款并发.使用标记-清除算法的gc. CMS是针对老 ...

  3. 图解 CMS 垃圾回收机制原理,-阿里面试题

    最近在整理JVM相关的PPT,把CMS算法又过了一遍,每次阅读源码都能多了解一点,继续坚持. 什么是CMS CMS全称 ConcurrentMarkSweep,是一款并发的.使用标记-清除算法的垃圾回 ...

  4. 高吞吐低延迟Java应用的垃圾回收优化

    高吞吐低延迟Java应用的垃圾回收优化 高性能应用构成了现代网络的支柱.LinkedIn有许多内部高吞吐量服务来满足每秒数千次的用户请求.要优化用户体验,低延迟地响应这些请求非常重要. 比如说,用户经 ...

  5. 图解 CMS 垃圾回收机制,你值得拥有(转 强烈推荐)

          首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 Java小组 工具资源 - 导航条 - 首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 Java小组 工具资源     ...

  6. CMS 垃圾回收日志

    CMS 垃圾回收日志 https://blogs.oracle.com/poonam/entry/understanding_cms_gc_logs http://www.blogjava.net/D ...

  7. CMS垃圾回收与G1垃圾回收

    CMS垃圾回收与G1垃圾回收的比较请参见:http://colobu.com/2015/04/14/G1-Getting-Started/

  8. Java虚拟机之垃圾回收详解一

    Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...

  9. 【java虚拟机序列】java中的垃圾回收与内存分配策略

    在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...

  10. java中存在垃圾回收机制,但是还会有内存泄漏的问题,原因是

    答案是肯定的,但不能拿这一句回答面试官的问题.分析:JAVA是支持垃圾回收机制的,在这样的一个背景下,内存泄露又被称为“无意识的对象保持”.如果一个对象引用被无意识地保留下来,那么垃圾回收器不仅不会处 ...

随机推荐

  1. STM32IO口模拟IIC时序

    正点原子IIC讲解:https://www.bilibili.com/video/BV1o8411n7o9/?spm_id_from=333.337.search-card.all.click& ...

  2. dart方法之间的调用和可选参数的使用

    01==> 方法封装 void main() { //直接调用 say('好好读书,天天向上'); } say(say) { print(say); } 02==>方法之间的调用 void ...

  3. MacOS修改应用快捷键的一般思路

    具体步骤为: 使用CheatSheet软件查看菜单项名称 在系统设置中修改菜单项的快捷键 举个例子:修改Chrome中左右切换tab的快捷键(系统语言为英文,中文同理) 默认采用Ccontrol Ta ...

  4. 玩转云端|天翼云边缘安全加速平台AccessOne实用窍门之让办公访问安全、高效又稳定

    本文分享自天翼云开发者社区<玩转云端|天翼云边缘安全加速平台AccessOne实用窍门之让办公访问安全.高效又稳定>,作者:天翼云社区官方账号 随着社会信息化程度不断提高,远程办公已经成为 ...

  5. SpringBoot利用@Async注解实现异步调用

    前言:异步编程是让程序并发运行的一种手段,使用异步编程可以大大提高我们程序的吞吐量,减少用户的等待时间.在Java并发编程中实现异步功能,一般是需要使用线程或者线程池.而实现一个线程,要么继承Thre ...

  6. Luogu P1784 数独 [ 模板 ] / P1074 靶形数独 题解 [ 蓝 ] [ 深搜 ] [ 剪枝 ] [ 卡常 ]

    数独模板 , 靶形数独 卡了 2h ,再也不想写数独了. 普通数独 思路 显然是对每个格子进行枚举,类似八皇后的方法去做,朴素方法是由 \((1,1)\) 到 \((9,9)\) 遍历过去. 优化 我 ...

  7. docker容器内部添加字体

    1.首先在windows电脑内找到字体拷贝到linux服务器,路径 C:\Windows\Fonts,linux的路径 /usr/share/fonts 2.复制到docker容器内部 docker ...

  8. DeepSeek-V3 解读:优化效率与规模

    DeepSeek-V3 是大语言模型(LLM)领域的一项变革性进展,为开源人工智能设定了新的标杆.作为一个拥有 6710 亿参数的专家混合(Mixture-of-Experts,MoE)模型,其中每个 ...

  9. 一种将历史地图坐标配准到GIS中的方法

    经常我们看到历史地图影像,比如谭图里面的各个历史朝代的大地图, 然后我们希望利用这个影像作为图层或者叫底图,然后在GIS软件上编辑一些矢量文件, 从而产生的地图矢量文件具有真实的经纬度坐标,不是单单的 ...

  10. STM32中如何使用printf()函数

    STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK) 在STM32串口通信程序中使用printf发送数据,非常的方便.可在刚开始使用的时候总是遇到问题,常见的是硬件访 ...