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

CMS垃圾回收器

CMS垃圾回收

CMS GC的官方名称为“Mostly Concurrenct Mark and Sweep Garbage Collector”(最大-并发-标记-清除-垃圾收集器)。
作用范围: 老年代
算法: 并发标记清除算法。
启用参数:-XX:+UseConMarkSweepGC
默认回收线程数:(处理器核心数量 + 3)/4Java9之后使用CMS垃圾收集器后,默认年轻代就为ParNew收集器,并且不可更改,同时JDK9之后被标记为不推荐使用,JDK14就被删除了。
设计目标/优点:避免在老年代垃圾收集时出现长时间的卡顿,主要通过两种手段来达成此目标:
第一,不对老年代进行整理,而是使用空闲列表(free-list)来管理内存空间的回收
第二,在mark-and-sweep(标记-清除)阶段的大部分工作和应用线程一起并发执行。

CMS的几个阶段

CMS 处理过程有七个步骤:
初始标记,会导致stw;
并发标记,与用户线程同时运行;
预清理,与用户线程同时运行;
可被终止的预清理,与用户线程同时运行;
重新标记 ,会导致swt;
并发清除,与用户线程同时运行;

或者说简化四个步骤
初始标记:仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The World”。
并发标记:进行GC Roots Tracing的过程,在整个过程中耗时最长。
重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。此阶段也需要“Stop The World”。
并发清除。

触发条件

1、如果没有设置-XX:+UseCMSInitiatingOccupancyOnly,虚拟机会根据收集的数据决定是否触发(建议线上环境带上这个参数,不然会加大问题排查的难度)。
2、老年代使用率达到阈值 CMSInitiatingOccupancyFraction,默认92%。
3、永久代的使用率达到阈值 CMSInitiatingPermOccupancyFraction,默认92%,前提是开启 CMSClassUnloadingEnabled。
4、新生代的晋升担保失败。
CMS的初始标记阶段,会扫描新生代对象,并把新生代的有效对象作为GC ROOT,用于第二阶段的扫描。

因为老年代对象可能只被新生代对象引用,故需要扫描新生代,

问题

1、垃圾碎片的问题
我们都知道CMS是使用的是标记-清除算法的,所以不可避免的就是会出现垃圾碎片的问题。
2、一般CMS的GC耗时80%都在remark阶段,remark阶段停顿时间会很长
3、concurrent mode failure
发生在cms正在回收的时候。执行CMS GC的过程中,同时业务线程也在运行,当年轻带空间满了,执行ygc时,需要将存活的对象放入到老年代,而此时老年代空间不足,这时CMS还没有机会回收老年带产生的,或者在做Minor GC的时候,新生代救助空间放不下,需要放入老年代,而老年代也放不下而产生的。
4、promotion failed
进行Minor GC时,Survivor空间不足,对象只能放入老年代,而此时老年代也放不下造成的,多数是由于老年代有足够的空闲空间,但是由于碎片较多,新生代要转移到老年带的对象比较大,找不到一段连续区域存放这个对象导致的。

解决方法:
垃圾碎片问题:需要用到这个参数:-XX:CMSFullGCsBeforeCompaction=n, 意思是说在上一次CMS并发GC执行过后,到底还要再执行多少次full GC才会做压缩。默认是0,也就是在默认配置下每次CMS GC顶不住了而要转入full GC的时候都会做压缩。

concurrent mode failure问题:-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=60
是指设定CMS在对内存占用率达到60%的时候开始GC。
为什么设置这两个参数呢?由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集。

remark阶段停顿时间会很长的问题:解决这个问题巨简单,加入-XX:+CMSScavengeBeforeRemark。在执行remark操作之前先做一次Young GC,目的在于减少年轻代对老年代的无效引用,降低remark时的开销。

相关文章:

  • Kotlin:协程基础
  • Leetcoder Day25| 回溯part05:子集+排列
  • 大概了解一下G1收集器
  • Redis 学习笔记 3:黑马点评
  • 服务器部署java 的docker项目,以及常用的一些命令
  • 可视化图文报表
  • Python爬虫进阶:爬取在线电视剧信息与高级检索
  • 【论文阅读】基于图像处理和卷积神经网络的板式换热器气泡识别与跟踪
  • iOS高级理论:分类和扩展
  • 多微服务合并为一个服务
  • 如何在debian上实现一键恢复操作系统?
  • 在IDEA中创建vue hello-world项目
  • Chapter 10 Basic Magnetics Theory
  • 微服务-实用篇
  • 机器视觉运动控制一体机在光伏汇流焊机器人系统的解决方案
  • 《Java编程思想》读书笔记-对象导论
  • Apache的80端口被占用以及访问时报错403
  • IP路由与转发
  • java取消线程实例
  • JS题目及答案整理
  • mac修复ab及siege安装
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • React as a UI Runtime(五、列表)
  • React16时代,该用什么姿势写 React ?
  • Unix命令
  • Vue 2.3、2.4 知识点小结
  • windows下mongoDB的环境配置
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 我感觉这是史上最牛的防sql注入方法类
  • 06-01 点餐小程序前台界面搭建
  • Python 之网络式编程
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​如何防止网络攻击?
  • #{} 和 ${}区别
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (Ruby)Ubuntu12.04安装Rails环境
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • **PHP二维数组遍历时同时赋值
  • .net 使用$.ajax实现从前台调用后台方法(包含静态方法和非静态方法调用)
  • .net和jar包windows服务部署
  • .NET框架设计—常被忽视的C#设计技巧
  • .NET性能优化(文摘)
  • [Android 13]Input系列--获取触摸窗口
  • [Android Pro] AndroidX重构和映射
  • [Android Pro] listView和GridView的item设置的高度和宽度不起作用
  • [Android Studio] 开发Java 程序
  • [Android]创建TabBar
  • [AUTOSAR][诊断管理][ECU][$37] 请求退出传输。终止数据传输的(上传/下载)
  • [BIZ] - 1.金融交易系统特点
  • [C]编译和预处理详解