为什么 Java 中 CMS 垃圾收集器在发生 Concurrent Mode Failure 时的 Full GC 是单线程的?
为什么 Java 中 CMS 垃圾收集器在发生 Concurrent Mode Failure 时的 Full GC 是单线程的?
在 CMS(Concurrent Mark-Sweep)垃圾收集器中,当发生 Concurrent Mode Failure 时,JVM 会执行一次 Full GC。与并发多线程的垃圾回收相比,这种 Full GC 是单线程的,导致暂停时间显著增加。
以下是具体原因及原理分析:
1. CMS 的设计目标
CMS 的核心目标是 低停顿,通过并发执行标记和清除阶段,与应用线程同时运行,最大限度地减少垃圾回收引起的停顿。然而,CMS 的标记-清除算法本质上 不进行内存压缩,因此在某些情况下(如内存碎片严重或空间不足),CMS 无法完成任务,从而触发 Concurrent Mode Failure。
2. Full GC 的触发原因
当 CMS 失败时,老年代空间不足,无法存放新分配或晋升的对象,这时 JVM 只能退而求其次,执行一次 Full GC 来回收整个堆空间。这种 Full GC 的特点是:
- 暂停所有应用线程(Stop-The-World)。
- 使用单线程执行标记、清理和内存整理操作。
3. 为什么 Full GC 是单线程的?
CMS 的 Full GC 是基于 Serial Old GC 的单线程实现,其设计原因如下:
原因 1:CMS 的备用策略
CMS 是为低延迟场景设计的,但它的设计并不适合 Full GC。当 CMS 失败时,JVM 转而调用传统的 Serial Old GC 作为备用策略。Serial Old GC 是单线程的,因此 CMS 的 Full GC 也只能是单线程。
原因 2:内存压缩需求
CMS 本身不支持 内存压缩(Compact),而 Full GC 在清理垃圾的同时,还需要对内存进行压缩以消除碎片化问题。这种压缩操作涉及对象移动和引用更新,较为复杂,单线程执行可以避免多线程同步带来的额外开销。
原因 3:历史兼容性
早期的 JVM 中,Serial Old GC 是默认的老年代垃圾回收器。当 CMS 失败时,JVM 选择直接使用现有的 Serial Old GC 实现 Full GC,而没有针对多线程优化。
原因 4:代码复杂性与性能权衡
在设计 CMS 时,Full GC 被视为一种 非常规操作,只在少数情况下触发。因此,JVM 没有对 CMS 的 Full GC 实现多线程优化,因为这会显著增加代码复杂性,而收益有限。
4. Full GC 的影响
Full GC 是单线程的,因此其执行时间较长,会显著增加应用的停顿时间。这对于低延迟应用是不利的。以下是其典型影响:
- 应用暂停时间从毫秒级增加到秒级。
- 高并发环境下会导致性能抖动。
5. 如何避免 Full GC?
为避免 Concurrent Mode Failure 和 Full GC 的发生,可以采取以下措施:
调整 CMS 启动阈值:
- 使用
-XX:CMSInitiatingOccupancyFraction=<N>提前启动 CMS 回收,避免内存空间被耗尽。
- 使用
增加老年代大小:
- 调整
-Xmx和-XX:NewRatio,为老年代分配更多内存空间。
- 调整
优化对象分配和晋升:
- 减少长生命周期对象直接分配到老年代,优化代码逻辑,降低新生代到老年代的晋升压力。
启用内存压缩:
- 使用
-XX:+UseCMSCompactAtFullCollection启用内存压缩,减少碎片化问题。
- 使用
使用其他垃圾回收器:
- 如果应用无法接受 CMS 的 Full GC 停顿时间,可以尝试使用 G1 GC 或其他现代垃圾回收器(如 ZGC、Shenandoah),这些回收器更适合低延迟场景。
6. 总结
CMS 在设计上并不擅长处理 Full GC,发生 Full GC 时转而调用单线程的 Serial Old GC。其原因主要在于历史兼容性、内存压缩需求,以及复杂性与收益的权衡。
核心要点:
- CMS 的 Full GC 是单线程的,因为它依赖 Serial Old GC 的实现。
- Full GC 主要用于清理碎片化内存,同时进行压缩。
- 为避免 Full GC,需要合理配置 CMS 参数,优化对象分配策略,或使用其他现代垃圾回收器。
合理的配置和调优可以大幅减少 Concurrent Mode Failure 的风险,降低 Full GC 对应用性能的影响。
为什么 Java 中 CMS 垃圾收集器在发生 Concurrent Mode Failure 时的 Full GC 是单线程的?的更多相关文章
- 《深入理解Java虚拟机》垃圾收集器
说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态 ...
- 想买保时捷的运维李先生学Java性能之 垃圾收集器
前言 垃圾收集算法是内存回收的方法论:垃圾收集器是内存回收的具体实现.Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商.不同版本的虚拟机所提供的垃圾收集器都有很大的差别,并且 ...
- 【JVM】JVM中的垃圾收集器
垃圾收集器组合 Serial+Serial Old Serial+CMS ParNew+CMS ParNew+Serial Old Paralle Scavenge + Serial Old Para ...
- G1垃圾收集器和CMS垃圾收集器 (http://mm.fancymore.com/reading/G1-CMS%E5%9E%83%E5%9C%BE%E7%AE%97%E6%B3%95.html#toc_8)
参考来源 JVM 体系架构 堆/栈的内存分配 静态和非静态方法的内存分配 CMS 回收算法 应用场景 CMS 垃圾收集阶段划分(Collection Phases) CMS什么时候启动 CMS缺点 G ...
- CMS垃圾收集器
介绍 CMS垃圾回收器的全称是Concurrent Mark-Sweep Collector,从名字上可以看出两点,一个是使用的是并发收集,第二个是使用的收集算法是Mark-Sweep.从而也可以推测 ...
- 2. Java中的垃圾收集 - GC参考手册
标记-清除(Mark and Sweep)是最经典的垃圾收集算法.将理论用于生产实践时, 会有很多需要优化调整的地点, 以适应具体环境.下面通过一个简单的例子, 让我们一步步记录下来, 看看如何才能保 ...
- 深入理解Java虚拟机笔记——垃圾收集器与内存分配策略
目录 判断对象是否死亡 引用计数器算法 可达性分析算法 各种引用 回收方法区 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 HotSpot算法实现 枚举根节点 GC停顿(Sto ...
- 实例透彻分析CMS垃圾收集器执行过程
CMS收集器收集步骤: 在上一次[https://www.cnblogs.com/webor2006/p/11055468.html]中已经对CMS的垃圾收集器有了一定的理论上的了解,其中提到了CMS ...
- 稳了!我准备了1个晚上的CMS垃圾收集器
面试官:今天还是来聊聊CMS垃圾收集器呗? 候选者:嗯啊... 候选者:如果用Seria和Parallel系列的垃圾收集器:在垃圾回收的时,用户线程都会完全停止,直至垃圾回收结束! 候选者:CMS的全 ...
- Java虚拟机学习 - 垃圾收集器
HotSpot JVM收集器 上面有7中收集器,分为两块,上面为新生代收集器,下面是老年代收集器.如果两个收集器之间存在连线,就说明它们可以搭配使用. Serial(串行GC)收集器 Serial收集 ...
随机推荐
- 提升质量:利用Coverage分析Python Web项目的测试覆盖
提升质量:利用Coverage分析Python Web项目的测试覆盖 鉴于不同框架的运行机制各有差异,当利用Coverage工具对Python Web项目的测试覆盖率进行分析时,必须采取针对性的方法来 ...
- 更换Linux系统镜像源
更换Linux系统镜像源 切换镜像源通常是为了提高软件包下载的速度和稳定性.以下是CentOS 7切换镜像源的一般步骤: 一.安装wget(如果尚未安装) 首先,需要确保系统中安装了wget工具,因为 ...
- initDB.sh初始化磁盘脚本centos7
新加磁盘初始化脚本 跳转:优化(2022-4-14) vim initDB.sh #!/bin/bash # auther by wangxp EXCLUDE_LIST='2,11' EXCLUDE_ ...
- Git与Github远程仓库使用
目录 连接远程仓库Github 配置git信息 生成key 添加Key 测试连通 Git基本了解 初级使用 初始化项目 建议修改编码显示 查看项目文件内容改动状态 修改好推送暂存区 提交本地版本库 推 ...
- P9869 [NOIP2023] 三值逻辑 题解
NOIP2023 T2 三值逻辑 题解 题面 思路 乍一看好像很并查集,而且不太难,但是, 注意到:按顺序运行这 \(m\) 条语句 事情并没有那么简单. 比如说如下情况: x1:=T x2:=x1 ...
- flutter-解决长按TextField出现英文(复制粘贴)问题
第一步 引入依赖 dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter 第二步 在main.dart中添加代码 ...
- DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
你好呀,我是歪歪. 五年前,2020 年,我写文章的时候曾经遇到过一个技术问题,百思不得其解,当时把那个问题归类为玄学问题. 后来也会偶尔想起这个问题,但是我早就不纠结于这个问题了,没再去研究过. 前 ...
- window本地部署deepseek
window本地部署deepseek 学习自[[教程]DeepSeek本地免费部署教程,丝滑不卡顿!带你解锁隐藏功能!]https://www.bilibili.com/video/BV1viFaeB ...
- Normalizing flow 流模型 | CS236深度生成模型Lec8学习笔记
主要参考资料:Stanford University CS236: Deep Generative Models Lec8. 这篇blog基本上是CS236 Lec8的刷课总结/刷课笔记. VAE 这 ...
- Typecho博客添加音乐外链支持Https
首先选个音质和音乐比较全面的音乐站,这里选了网易云音乐,自己手机用的网易云音乐app,存了好多歌单,所以就选他了,但是想获取音乐文件链接,得去这儿:季春二九音乐站 其实很简单,参考下面. 1.先找到网 ...