一文带你了解CMS收集器:并发低停顿收集器

news2025/6/19 1:45:23

一、工作流程

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。互联网网站或者基于B/S系统(B/S系统是指Browser/Server系统,也就是基于浏览器和服务器的系统架构)的服务端应用通常会关注服务的响应速度,希望系统停顿的时间尽可能短。CMS收集器就非常符合此类应用的需求。

CMS收集器基于标记-清除算法实现,包括四个步骤:

1)初始标记

2)并发标记

3)重新标记

4)并发清除

其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快;并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行;而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短;最后是并发清除阶段,清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。

由于再整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的·。

 

二、性能分析

优点:并发收集、低停顿。

缺点:

1、CMS收集器对处理器资源非常敏感。

事实上,面向并发设计的程序都对处理器资源比较敏感。在并发阶段,它虽然不会导致用户线程停顿,但却会因为占用了一部分线程(或者说处理器的计算能力)而导致应用程序变慢,降低总吞吐量。

CMS默认启动的回收线程数是(处理器核心数量+3)/4,也就是说,如果处理器核心数在四个或以上,并发回收时垃圾收集线程只占用不超过25%的处理器运算资源,并且会随着处理器核心数量增加而下降。但是当处理器核心数量不足四个时,CMS对用户程序的影响就可能变得很大。

为了缓解这种情况,虚拟机提供了一种“增量式并发收集器”的CMS收集器变种,类似于单核操作系统靠抢占式多任务来模拟多核并行多任务的思想。在并发标记、清理的时候让收集器线程、用户线程交替运行,尽量减少垃圾收集线程的独占资源时间。这样整个垃圾收集时间更长,但对用户程序的影响就会少一些。实践证明增量式CMS收集器效果很一般,JDK 9发布后i-CMS模式被完全废弃。

2、会产生大量空间碎片。

基于“标记-清除”算法实现的收集器,收集结束时会产生大量空间碎片。空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现老年代还有很多剩余空间,但就是无法找到足够大的连续空间来分配当前对象,而不得不提前触发一次Full GC的情况。

为了解决这个问题,CMS收集器提供了一个-XX:+UseCMS-CompactAtFullCollection开关参数(默认是开启的,此参数从JDK 9开始废弃),用于在CMS收集器不得不进行Full GC时开启内存碎片的合并整理过程,由于这个内存整理必须移动存活对象,(在Shenandoah和ZGC出现前)是无法并发的。这样空间碎片问题是解决了,但停顿时间又会变长,因此虚拟机设计者们还提供了另外一个参数-XX:CMSFullGCsBefore-Compaction(此参数从JDK 9开始废弃),这个参数的作用是要求CMS收集器在执行过若干次(数量由参数值决定)不整理空间的Full GC之后,下一次进入Full GC前会先进行碎片整理(默认值为0,表示每次进入Full GC时都进行碎片整理)。

3、由于CMS收集器无法处理“浮动垃圾”(Floating Garbage),有可能出现“Con-current Mode Failure”失败进而导致另一次完全“Stop The World”的Full GC的产生。

在CMS(Concurrent Mark Sweep)垃圾收集器中,它使用了一种并发标记和清除的算法来减少垃圾收集对应用程序的停顿时间。然而,CMS收集器无法处理"浮动垃圾"(Floating Garbage),也就是在并发标记阶段开始后,应用程序产生的新垃圾对象。 当CMS收集器在并发标记阶段执行时,应用程序仍然在运行并产生新的垃圾对象。这些新的垃圾对象无法被并发标记阶段捕获到。如果在并发标记阶段结束之前,垃圾对象的数量变得过多,超过了CMS收集器的阈值,那么就会发生"Con-current Mode Failure"(并发模式失败)。 "Con-current Mode Failure"表示CMS收集器无法在预期的时间内完成垃圾收集,因为并发标记和清除的过程无法继续执行。当发生"Con-current Mode Failure"时,CMS收集器会触发一次完全的"Stop The World"的Full GC,即执行一次完全的垃圾收集过程。 Full GC会导致较长的停顿时间,因为它需要暂停应用程序的执行,以便对整个Java堆进行垃圾回收。这段停顿时间可能会对应用程序的响应性产生负面影响。

4、同样也是由于在垃圾收集阶段用户线程还需要持续运行,那就还需要预留足够内存空间提供给用户线程使用,因此CMS收集器不能像其他收集器那样等待到老年代几乎完全被填满了再进行收集,必须预留一部分空间供并发收集时的程序运作使用。

在JDK 5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活,这是一个偏保守的设置,如果在实际应用中老年代增长并不是太快,可以适当调高参数-XX:CMSInitiatingOccu-pancyFraction的值来提高CMS的触发百分比,降低内存回收频率,获取更好的性能。到了JDK 6时,CMS收集器的启动阈值就已经默认提升至92%。但这又会更容易面临另一种风险:要是CMS运行期间预留的内存无法满足程序分配新对象的需要,就会出现一次“并发失败”(Concurrent Mode Failure),这时候虚拟机将不得不启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来重新进行老年代的垃圾收集,但这样停顿时间就很长了。所以参数-XX:CMSInitiatingOccupancyFraction设置得太高将会很容易导致大量的并发失败产生,性能反而降低,用户应在生产环境中根据实际应用情况来权衡设置。

三、知识补充

在Java虚拟机(JVM)中,Full GC(Full Garbage Collection)是指对整个Java堆进行垃圾回收的过程。Full GC会尽可能回收所有不再使用的对象,包括年轻代和老年代中的对象。 Full GC通常会涉及以下几个步骤:

  1. 停止应用程序的执行:Full GC需要停止应用程序的执行,以便进行垃圾回收操作。这个过程可能会导致一段时间的应用程序暂停,也就是停顿时间(Pause Time)。
  2. 标记阶段(Marking Phase):Full GC会标记所有活动对象,即从根对象开始,递归遍历所有可达对象,并将其标记为活动对象。
  3. 清除阶段(Sweeping Phase):Full GC会清除所有未标记(即不可达)的对象,释放它们所占用的内存空间。
  4. 压缩阶段(Compaction Phase):Full GC会对内存空间进行整理和压缩,以减少碎片化,使得内存空间得到更好的利用。 Full GC通常在以下情况触发:
  5. 当年轻代无法容纳新的对象时,会触发一次Minor GC(部分垃圾回收)和一次Full GC(完全垃圾回收)。
  6. 当老年代空间不足时,会触发一次Full GC。
  7. 当显式调用System.gc()方法时,会触发一次Full GC,但这只是建议垃圾回收器执行回收操作,并不能保证立即执行。 Full GC的频率和性能会对应用程序的性能产生一定的影响,较长的停顿时间可能会导致应用程序的响应性下降。因此,在开发和调优过程中,需要综合考虑内存分配、垃圾回收算法和堆大小等因素,以减少Full GC的频率和停顿时间,提升应用程序的性能。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/897294.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ADC静态特性测试

测试环境搭建: 码密度分析法的局限性 更新: MATLAB R2020a之后的版本,更新了函数 “inldnl()”,可以自动计算INL和DNL。具体用法看MATLAB说明文档即可。

Linux —— 进程间通信

目录 一,进程间通信 二,管道 匿名管道 命名管道 一,进程间通信 进程间通信(IPC,InterProcess Communication),即在不同进程之间进行信息的传播或交换;由于一般进程用户地址空间是…

C++ STL容器适配器(详解)

STL容器适配器 什么是适配器,C STL容器适配器详解 在详解什么是容器适配器之前,初学者首先要理解适配器的含义。 其实,容器适配器中的“适配器”,和生活中常见的电源适配器中“适配器”的含义非常接近。我们知道,无…

Python土力学与基础工程计算.PDF-螺旋板载荷试验

python 求解代码如下: 1. import numpy as np 2. 3. # 已知参数 4. p_a 100 # 标准压力, kPa 5. p np.array([25, 50, 100, 200) # 荷载, kPa 6. s np.array([2.88, 5.28, 9.50, 15.00) / 10 # 沉降量, cm 7. D 10 # 螺旋板直…

opencv直方图与模板匹配

import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方图 cv2.calcHist(images,channels,mask,histSize,ran…

2023-8-18 最长连续不重复子序列

题目链接&#xff1a;最长连续不重复子序列 #include <iostream>using namespace std;const int N 100010; int n; int a[N], s[N];int main () {cin >> n;for(int i 0; i < n; i ) cin >> a[i];int res 0;for(int i 0, j 0; i < n; i){s[a[i]];w…

jenkins 是什么?

一、jenkins 是什么&#xff1f; Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具&#xff0c;起源于Hudson&#xff0c;主要用于持续、自动的构建/测试软件项目、监控外部任务的运行。Jenkins用Java语言编写&#xff0c;可在Tomcat等流行的servlet容器中运行&#…

集简云 x 车邻邦丨实现金蝶云星辰快速集成第三方系统,实现单据自动同步

品牌故事 车邻邦成立于2009年&#xff0c;专注于汽车贴膜及美容装饰服务&#xff0c;核心业务是为高端4S店、4S集团提供汽车精品领域“产品营销施工售后”的一站式解决方案。 公司成立至今已有14年之久&#xff0c;累计服务客户数百家、累计服务车辆百万台次&#xff0c;口碑…

windows结束explorer进程后桌面白屏解决

背景 结束进程时一不小心一起删掉explorer.exe &#xff0c;这个文件结束桌面就一片白 &#xff0c; 解决&#xff1a; 不要关机&#xff0c;同时按键盘上ctrlshiftesc ,重新进入任务管理器&#xff0c;接着点“进程”选项&#xff0c;按左上角文件选项&#xff0c;进入下拉菜单…

2023年Java核心技术面试第二篇(篇篇万字精讲)

目录 四. 强引用&#xff0c;软引用&#xff0c;弱引用&#xff0c;幻象引用之间的区别&#xff1f; 1.前言 2.强引用 2.1 强引用赋值为null 2.2 超过了引用的作用域 2.2.1 描述&#xff1a; 2.2.2 作用域内&#xff1a; 2.2.3 不在作用域内: 3. 软引用&#xff08;SoftRefere…

助力工业物联网,工业大数据之服务域:服务器性能监控Prometheus及项目总结【三十五】

服务器性能监控Prometheus及项目总结 01&#xff1a;目标 服务器性能监控工具 整体作为了解实现部署安装以及监控构建 项目总结 需求分析、技术架构数仓设计&#xff1a;主题划分、分层设计、维度设计优化、问题、数据量及集群规模简历模板 02&#xff1a;监控需求及常见工…

Cat(6):API介绍—Metric

Metric 用于记录业务指标、指标可能包含对一个指标记录次数、记录平均值、记录总和&#xff0c;业务指标最低统计粒度为1分钟。 # Counter Cat.logMetricForCount("metric.key"); Cat.logMetricForCount("metric.key", 3); # Duration Cat.logMetricForDu…

java学习004

常用数据结构对应 php中常用的数据结构是Array数组&#xff0c;相对的在java开发中常用的数据结构是ArrayList和HashMap&#xff0c;它们可以看成是array的拆分&#xff0c;一种简单的对应关系为 PHPJAVAArray: array(1,2,3)ArrayListlArray: array(“name” > “jack”,“…

通过请求头传数据向后端发请求

axios &#xff08;get post请求、头部参数添加&#xff09;傻瓜式入门axios_axiospost请求参数_web_blog的博客-CSDN博客

【第八讲---视觉里程计2】

在图像中提取特征点并计算特征描述&#xff0c;非常耗时 通过计算描述子距离在不同图像中寻找特征匹配&#xff0c;也非常耗时 利用通过匹配点信息计算相机位姿&#xff0c;没什么问题 我们可以采用以下方法进行改进&#xff1a; 光流&#xff1a;通过其他方式寻找匹配点直接法…

原型对象的简单了解

在前面学习java有一个概念叫做继承&#xff0c;方便我们对父类方法、变量等的调用。对前端的学习我们需要让对象可以访问和继承其他对象的属性和方法&#xff0c;就需要了解原型对象&#xff0c;以及原型链。 一、原型 构造函数通过原型分配的函数是所有对象所共享的。每一个构…

SpringBoot Vue 微人事(十)

职位管理前后端对接问题解决 因为mysql字段关联其他表&#xff0c;进行约束了&#xff0c;删除不了的&#xff0c;就报未知错误是不合适的 需要在后端写一个全局异常类 删掉了MySQLIntegrityConstraintViolationException这个异常类才能导包&#xff0c;能用 RestController…

AutoSAR系列讲解(深入篇)13.6-Mcal Mcu时钟的配置

目录 一、EB的Mcu模块结构 二、时钟的配置 对Mcu的配置主要就是其时钟树的配置,但是EB将GTM、ERU等很多重要的模块也都放在了Mcu里面做配置,所以这里的Mcu是一个很庞大的模块, 我们目前只讲时钟树的部分 一、EB的Mcu模块结构 1. 所有的模块都基本上是这么些配置类别,Mc…

Spark 图计算ONEID 进阶版

0、环境信息 本文采用阿里云maxcompute的spark环境为基础进行的&#xff0c;搭建本地spark环境参考搭建Windows开发环境_云原生大数据计算服务 MaxCompute-阿里云帮助中心 版本spark 2.4.5&#xff0c;maven版本大于3.8.4 ①配置pom依赖 详见2-1 ②添加运行jar包 ③添加配置信…

SAP SQL/CDS新功能货币汇率转换CURRENCY_CONVERSION( p1 = a1, p2 = a2, … )

1. 示例 PARAMETERS: p_waers TYPE mseg-waers OBLIGATORY DEFAULT USD.SELECT SUM( currency_conversion( amount a~hsl, "转换的金额source_currency b~isocd, "源货币target_currency p_waers, "目标货币exchange_rate_dat…