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

cms垃圾回收

cms垃圾回收

  • CMS概述
  • CMS收集器整体流程
    • 初始标记
    • 并发标记
    • 重新标记
    • 并发清除
  • CMS卡表
    • 什么是卡表(card table)
    • 什么是mod-union table

CMS概述

CMS(Concurrent Mark Sweep)收集器是Java虚拟机中的一种老年代(old Generation)垃圾收集器,他主要目标是减少垃圾收集时的应用程序停顿(Stp)时间。

CMS使用并发的方式执行垃圾回收,使用的是“标记-清理”算法,尽量减少在垃圾收集过程中程序的暂停时间,适用于对服务响应速度要求较高的场景,例如互联网的B/S系统的服务端Java应用。

CMS垃圾收集器作为一款专注降低停顿时间的垃圾回收器,其主要特点是低停顿和并发:

  1. 并发
    CMS被设计为一款并发、低停顿的垃圾收集器,使得在垃圾回收过程中用户线程停顿时间很短,有助于保障系统的响应速度。
  2. 低停顿
    由于其并发特性,CMS的停顿时间相对较短,适用于对服务响应速度要求高的应用场景。

但是,由于CMS的实现机制,也存在着下面这些问题:

  1. 对CPU资源敏感:
    CMS对CPU资源敏感,因为在并发阶段虽然不会导致用户线程停顿,但会占用一部分线程(CPU资源),可能导致应用程序整体变慢,降低总吞吐量。
  2. 无法处理浮动垃圾
    由于CMS在并发清理阶段用户线程仍在运行,新的垃圾可能在标记过程之后(重新标记之后)的“并发清理阶段”产生。因为在并发清理阶段用户线程和GC线程是并发运行的,而CMS不能在当前收集中处理这部分浮动垃圾。
    所以CMS收集器必须预留一部分空间给用户用户线程使用,不能等到老年代占用100%再进行收集
  3. 对CPU数量要求较高
    CMS默认启动的回收线程数为(CPU数量+3)/4,当CPU不足4个时,可能对用户程序影响较大。
  4. 内存碎片问题
    基于“标记-清除”算法的CMS会导致大量空间碎片的产生,可能对大对象分配的时候可能会产生Full GC,因为可能出现老年代空间虽有剩余但无法找到足够大连续空间来分配当前对象。

CMS收集器整体流程

CMS垃圾收集器是一种并发执行的垃圾回收器。其执行过程分为初始标记,并发标记,重新标记,和并发清理。流程如下:

在这里插入图片描述

初始标记

初始标记只是标记GC Roots能直接关联到的对象,但需要“Stop The World”停顿,即在此期间暂停所有应用线程。这个过程在JDK 7 之前是单线程(因为GC Roots直接关联的对象相对较少),JDK 8之后是多线程的方式进行初始标记。
由于GC Root直接关联的对象小,因此可以快速的将这些对象标记出来,以减少“Stop The World”的时间。

并发标记

与应用线程一起运行,是CMS最主要的工作阶段,通过直达对象,扫描全部的对象,进行标记

重新标记

STW,修正并发标记时由于应用程序还在并发运行产生的对象的修改,多线程,速度快,需要全局停顿

由于在并发标记阶段,用户线程还是在工作的,因为有可能会产生新的对象,新对象主要通过以下三个途径产生:

  • 年轻代对象晋升到老年代,可能产生新的存活对象
  • 大对象直接被分配到老年代,可能产生新的存活对象
  • 老年代和年轻代对应的应用关系发生变化。

JVM会通过Card(卡片)的方式将发生变化的老年代区域标记为“脏”区域,也就是所谓的卡片标记(Card Marking)来对新增对象的存活状态进行重新标记。

并发清除

与应用程序一起运行,为何采用清除算法?CMS主要关注低延迟,因而采用并发方式,清理垃圾时,应用程序还在运行,如何采用压缩算法,则涉及到要移动应用程序的存活对象,此时不停顿,是很难处理的,一般需要停顿下,移动存活对象,再让应用程序继续运行,但这样停顿时间变长,延迟变大,所以CMS采用清除算法。

CMS卡表

什么是卡表(card table)

试想一下,在进行young gc时,如何判断是否存在老年代到新生代的引用?
一个简单的办法是扫描整个老年代,但是这个代价太大了,因此jvm引入了卡表来解决这个问题。

卡表又被卡片标记(card marking),其原理为,在逻辑上将老年代空间分割为若干个固定大小的连续区域,分割出来的每一个区域就称为卡片(card)。另外每个卡片又一个与其对应的标记位,最简单的实现方案是由字节数组实现,以卡的编号作为索引,每个卡的大小通常介于128-512字节之间,一般使用2的幂字节大小,例如hotspot使用512字节。

当卡片内部发生应用变化时(指针写操作),写屏障会将该卡在卡表中对应的字节标记为脏(dirty)。

有了卡表后,在YGC时,只需要将卡表中被标记为dirty的card也作为扫描范围,就可以保证整个老年代也不会有遗漏了。

什么是mod-union table

通过上面的card table介绍,我们知道card table会记录下老年代所有发生过引用变化对象所在的card,而CMS在并发标记阶段,也需要记录下老年代发生引用变化的对象以便后续重新扫描,那是否可以直接复用card table呢?

不行的。这是因为每次ygc过程中都涉及重置和重新扫描card table,这样是满足了ygc的需求,但却破坏了CMS的需求,cms需要的信息可能被ygc重置掉了。为了避免丢失信息,于是在card table之外另加家了一个bitmap,叫做mon-union table。

在cms并发标记正在运行的时候,每当发生一次ygc,当ygc重置card table里的某个记录时,就会更新mon-union table对应的bit,相当于把car table里的信息转移到了mod-union table里了。


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

相关文章:

  • python | OpenCV小记(一):cv2.imread(f) 读取图像操作(待更新)
  • 快速提升网站收录:避免常见SEO误区
  • VS2008 - debug版 - 由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。
  • zookeeper-3.8.3-基于ACL的访问控制
  • 探索性测试与自动化测试的结合
  • 电商系统-用户认证(三)基于公钥解析JWT令牌
  • MySQL-----事务
  • 差分逻辑电平 — LVDS、CML、LVPECL、HCSL互连
  • SQLiteC/C++接口详细介绍之sqlite3类(五)
  • em、px、rem、vh、vw 的区别
  • 掌握C#: 从基础到精通 - 中级实战练习集
  • mac启动skywalking报错
  • 亚马逊云科技 Lambda 运行selenium
  • 基于Springboot+Redis+mysql实现的闲置二手交易网站管理系统
  • layui table列表重载后保持进度条位置不变
  • npm下载慢换国内镜像地址
  • C++ 虚函数表
  • STM32 Simulink 自动代码生成电机控制——霍尔有感六步方波仿真到开发板运行
  • 项目需求:实现 PDF 添加水印,这五种方案送上!
  • 关于分布式微服务数据源加密配置以及取巧方案(含自定义加密配置)
  • ChatGPT编程—实现小工具软件(批量替换文本、批量处理图像文件)
  • linux最佳入门(笔记)
  • 【TB作品】MSP430,单片机,Proteus仿真,单片机通信,串口通信
  • 计算机设计大赛 题目:基于机器视觉的图像矫正 (以车牌识别为例) - 图像畸变校正
  • 基于MATLAB的OFDM系统实现
  • 卫生间设计黄金法则!贴心小技巧,让你的卫生间瞬间变宽敞!福州中宅装饰,福州装修