首页 > 其他分享 >CMS垃圾收集器

CMS垃圾收集器

时间:2024-03-13 23:01:06浏览次数:23  
标签:标记 对象 收集器 回收 并发 GC 垃圾 CMS

 CMS概述

CMS(Concurrent Mark Sweep)收集器是一种以获取 最短回收停顿时间为目标的收集器。

CMS收集器主要用于要求低延迟(即:提高响应速度)的互联网项目。

设置CMS收集器参数:-XX:+UseConcMarkSweepGC。

采用的是"标记-清除算法",整个过程分为4步

(1)初始标记 CMS initial mark     标记GC Roots直接关联对象,不用Tracing,速度很快
(2)并发标记 CMS concurrent mark  进行GC Roots Tracing
(3)重新标记 CMS remark           修改并发标记因用户程序变动的内容
(4)并发清除 CMS concurrent sweep 清除不可达对象回收空间,同时有新垃圾产生,留着下次清理称为浮动垃圾

为什么我的CMS回收流程图上初始标记是单线程,为什么不使用多线程呢?

初始化标记阶段是串行的,这是JDK7的行为。JDK8以后默认是并行的,可以通过参数

-XX:+CMSParallelInitialMarkEnabled控制

这是因为在JDK7以前应用程序线程大多使用的是一个或者两个cpu核心,在这种情况下如果使用多线程进行初始标记,线程的上下文频繁切换会增加额外的开销,还不如直接使用单线程进行初始标记,效率更高

而JDK8以后应用程序线程大多是多个CPU核心了,所以使用多线程的初始标记,可以提高效率

而重新标记的时候,由于我的并发标记阶段已经开启了多个线程,所以可以直接使用多线程进行重新标记,没有额外的线程开销,所以重新标记阶段使用的是多线程

CMS的两种模式与一种特殊策略

Backgroud CMS 

实际上我们的并发标记还能被整理成两个流程

(1)初始标记

(2)并发标记

(3)并发预处理 

(4)可中止的预处理

(5)重新标记

(6)并发清除

为什么我们的并发标记细化之后还会额外有两个流程出现呢?

讨论这个问题之前,我们先思考一个问题,假设CMS要进行老年代的垃圾回收,我们如何判断被年轻代的对象引用的老年代对象是可达对象。

也就是这张图,当老年代被回收的时候,我们如何判断A对象是存活对象。

答:必须扫描新生代来确定,所以CMS虽然是老年代的垃圾回收器,却需要扫描新生代的原因。

问题2:既然这个时候我需要扫描新生代,那么全量扫描会不会很慢

答:肯定会的 ,但是接踵而来的问题:既然会很慢,我们的停顿时间很长,可是CMS的目标是什么

CMS(Concurrent Mark Sweep)收集器是一种以获取 最短回收停顿时间为目标的收集器。这不是与他的设计理念不一致吗?

思考:怎么让我们的回收变快

答:肯定是垃圾越少越快。所以我们的CMS想到了一种方式,就是我先进行新生代的垃圾回收,也就是一次young GC,回收完毕之后。是不是我们新生代的对象就变少了,那么我再进行垃圾回收,是不是就变快了。

所以,CMS有两个参数:

CMSScheduleRemarkEdenSizeThreshold 默认值:2M

CMSScheduleRemarkEdenPenetration 默认值:50%

Foregroud CMS

其实这个也是CMS一种收集模式,但是他是并发失败才会走的模式,简单来说,也就是我去进行并发标记的时候,内存不够了,这个时候我会进入STW,并且开始全局Full GC

-XX:CMSInitiatingOccupancyFraction  

在使用CMS收集器的情况下,指定老年代被使用的内存空间的阈值,达到该阈值则触发Full GC。
-XX:+UseCMSInitiatingOccupancyOnly

指定用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction参数的值),如果不指定,JVM仅在第一次使用设定值,后续则会根据运行时采集的数据做自动调整,如果指定了该参数,那么每次JVM都会在到达规定设定值时才进行GC。不过大多数情况下,JVM都能够作出更好的垃圾收集决策,所以如果不是很有信心的话,不建议使用该参数,放心的把决定权交给JVM。

按照默认值 当老年代达到 92 %时,会触发CMS回收。

CMS的标记压缩算法-----MSC(Mark Sweep Compact

他的回收方式其实就是我们的滑动整理,并且进行整理的时候一般都是两个参数

-XX:+UseCMSCompactAtFullCollection 
-XX:CMSFullGCsBeforeCompaction=0
这两个参数表示多少次FullGC后采用MSC算法压缩堆内存,0表示每次FullGC后都会压缩,同时0也是默认值

碎片问题也是CMS采用的标记清理算法最让人诟病的地方:Backgroud CMS采用的标记清理算法会导致内存碎片问题,从而埋下发生FullGC导致长时间STW的隐患。

所以如果触发了FullGC,无论是否会采用MSC算法压缩堆,那都是ParNew+CMS组合非常糟糕的情况。因为这个时候并发模式已经搞不定了,而且整个过程单线程,完全STW,可能会压缩堆(是否压缩堆通过上面两个参数控制),真的不能再糟糕了!想象如果这时候业务量比较大,由于FullGC导致服务完全暂停几秒钟,甚至上10秒,对用户体验影响得多大。

三色标记

在并发标记阶段,由于标记期间与应用程序并行,对象间的引用关系可能发生变化,因此采用三色标记的方式对对象进行标记,标记过程分为三种颜色:白色、灰色、黑色。

黑色:表示对象已经被垃圾收集器访问过, 且这个对象的所有引用都已经扫描过。 黑色的对象代表已经扫描过, 它是安全存活的, 如果有其他对象引用指向了黑色对象, 无须重新扫描一遍。 黑色对象不可能直接(不经过灰色对象) 指向某个白色对象。

灰色:表示对象已经被垃圾收集器访问过, 但该对象上至少存在一个引用还没有被扫描过。

白色:表示对象尚未被垃圾收集器访问过。 在可达性分析刚刚开始的阶段, 所有的对象都是白色的, 若在分析结束的阶段, 仍然是白色的对象, 即代表不可达。

标记过程

1)初始时,所有对象都在 【白色集合】中。

2)将GC Roots直接引用到的对象转移【灰色集合】中。

3)从灰色集合中获取对象:

将本对象引用到的其他对象全部转移【灰色集合】中。

将本对象转移【黑色集合】中。

三色标级存在漏标和多标问题。

漏标

漏标只有同时满足以下两个条件时才会发生:

条件一:灰色对象 断开了 白色对象的引用;即灰色对象 原来成员变量的引用 发生了变化。

条件二:黑色对象 重新引用了 该白色对象;即黑色对象 成员变量增加了 新的引用。

如图所示:

图中,有ABCD四个对象,A依赖B和C,C依赖D,初始标记完成后A对象已经被扫描过标为灰色,其他对象为白色;继续扫描B和C,当B和C扫描完后,A变成了黑色,B变成了灰色,C是黑色,D还是白色。此时如果应用程序将B和D的引用去掉,让C依赖D,建立起C和D的关系之后B变成了黑色。此时问题产生了,C已经是黑色,不会再对其依赖对象进行扫描,但事实上C还有一个依赖对象D没有被扫描。如果进行垃圾回收,D会被回收掉,这就是漏标问题。 

漏标解决方案

增量更新:就是当黑色对象插入新的指向白色对象的引用关系时, 就将这个新插入的引用记录下来, 等并发扫描结束之后, 再将这些记录过的引用关系中的黑色对象为根, 重新扫描一次。 这可以简化理解为, 黑色对象一旦新插入了指向白色对象的引用之后, 它就变回灰色对象了。

多标

如图所示:

图中,有ABCD四个对象,AB是黑色,C是灰色,D是白色,当GC正在扫描D时,B被置空了,此时B理应被回收,但是因为GC不会对黑色对象做重复扫描,所以B还是黑色,在进行垃圾清理时不会被回收,只能等下次GC时再进行重新标记扫描。这种情况相对于漏标来说不会导致系统出BUG,这部分本应该回收但是没有回收到的内存,被称之为“浮动 垃圾”。浮动垃圾并不会影响垃圾回收的正确性,只是需要等到下一轮垃圾回收中才被清除。

并发预处理

并发预清理主要是处理并发阶段因引用关系发生变更而未标记到的存活对象(即:扫描所有标记为Direty的Card )。

可终止预处理

可终止预处理阶段与并发预处理节点一样,主要是处理并发阶段因引用关系发生变更而未标记到的存活对象(即:扫描所有标记为Direty的Card )。但是可终止预处理是有条件触发的,触发条件由CMS的两个参数控制:

  • 参数CMSScheduleRemarkEdenSizeThreshold,默认值:2M。(Threshold:门槛)

  • 参数CMSScheduleRemarkEdenPenetration,默认值:50%。(Penetration:占有率)

这两个参数一般是组合使用,即:当Eden空间使用超过2M时,启动可终止预处理,当Eden空间使用率到达50%时中断,进入重新标记阶段。

同时,CMS提供了一个参数CMSMaxAbortablePrecleanTime (默认为5S),表示不管Eden空间使用率是否到达参数CMSScheduleRemarkEdenPenetration配置的值,都会中断,进入重新标记阶段。

最后,CMS还提供参数CMSScavengeBeforeRemark(Scavenge:清扫)(默认关闭,建议开启,开启方式:-XX:+CMSScavengeBeforeRemark),表示进入重新标记前强行执行一次Minor GC。

记忆集

当我们进行young gc时,我们的gc roots除了常见的栈引用、静态变量、常量、锁对象、class对象这些常见的之外,如果 老年代有对象引用了我们的新生代对象 ,那么老年代的对象也应该加入gc roots的范围中,但是如果每次进行young gc我们都需要扫描一次老年代的话,那我们进行垃圾回收的代价实在是太大了,因此我们引入了一种叫做记忆集的抽象数据结构来记录这种引用关系。

记忆集是一种用于记录从非收集区域指向收集区域的指针集合的数据结构。

卡表

记忆集是我们针对于跨代引用问题提出的思想,而卡表则是针对于该种思想的具体实现。(可以理解为记忆集是结构,卡表是实现类)

(1) 卡表是使用一个字节数组实现:CARD_TABLE[],每个元素对应着其标识的内存区域一块特定大小的内存块,称为"卡页"。hotSpot使用的卡页是2^9大小,即512字节

(2) 一个卡页中可包含多个对象,只要有一个对象的字段存在跨代指针,其对应的卡表的元素标识就变成1,表示该元素变脏,否则为0。GC时,只要筛选本收集区的卡表中变脏的元素加入GC Roots里。

并发标记的时候,A对象发生了所在的引用发生了变化,所以A对象所在的块被标记为脏卡

继续往下到了重新标记阶段,修改对象的引用,同时清除脏卡标记。

CMS的线程数计算公式

-XX:ParallelGCThreads

-XX:ParallelGCThreads=m // STW暂停时使用的GC线程数,一般用满CPU

其中ParallelGCThreads 参数的默认值是:

CPU核心数 <= 8,则为 ParallelGCThreads=CPU核心数,比如4C8G取4,8C16G取8

CPU核心数 > 8,则为 ParallelGCThreads = CPU核心数 * 5/8 + 3 向下取整

-XX:ConcGCThreads

-XX:ConcGCThreads=n // GC线程和业务线程并发执行时使用的GC线程数,一般较小

ConcGCThreads的默认值则为:

ConcGCThreads = (ParallelGCThreads + 3)/4 向下取整

标签:标记,对象,收集器,回收,并发,GC,垃圾,CMS
From: https://blog.csdn.net/CUITLY_/article/details/136653367

相关文章

  • 优秘智能开源AICMS:快速开发AIGC应用的必备,SAAS营销管理和AI的API全方位接入
    随着人工智能技术的飞速发展,AIGC(AIGeneratedContent)已经成为了当今科技领域的热门话题。为了帮助更多的企业和开发者快速开发AIGC应用,优秘智能近日开源了其强大的AICMS(AIContentManagementSystem)平台,助力开发者高效构建各类AIGC应用。一、优秘智能AICMS简介优秘智能是......
  • 全新QSiC 1200V 模块:GCMS020A120S1-E1、GCMS040A120S1-E1、GCMX020B120S1-E1、GCMS020
    全新QSiC1200VSOT-227SiC模块,提升能源标准,这些超高效模块支持电动汽车、医疗电源和太阳能大功率应用的创新设计。特点低开关损耗低结至外壳热阻非常坚固,易于安装直接安装到散热器上(隔离封装)超低损耗的高频操作SiCSBDs的零反向恢复电流SiCMOSFETs的小关断尾电流低杂散电感......
  • CMS垃圾收集器
    CMSGC的英文名为:“MostlyConcurrentMarkandSweepGarbageCollector”(最大-并发-标记-清除-垃圾收集器)。作用范围:老年代算法:并发标记清除算法。启用参数:-XX:+UseConMarkSweepGC默认回收线程数:(处理器核心数量+3)/4Java9之后使用CMS垃圾收集器后,默认年轻代就为ParNew收......
  • Java11改进的垃圾回收器
       传统的C/C++等编程语言,需要程序员负责回收已经分配的内存。显示进行垃圾回收是一件比较困难的事情,因为程序员并不总是知道内存应该何时被释放。如果一些分配出去的内存得不及时回收,就会引起系统运行速度下降,甚至导致程序瘫痪,这种现象被称为内存泄漏。总体而言,显示进行垃圾......
  • 9 JVM垃圾回收
    9JVM垃圾回收方法区的回收方法区中能回收的内容主要就是不再使用的类。判定一个类可以被回收,需要同时满足下面三个条件:1.此类所有实例对象都已经被回收,在堆中不存在任何该类的实例对象以及子类对象2.加载该类的类加载器已经被回收3.该类对应的java.lang.Class对象没有在任......
  • 易基因:NAR:RCMS编辑系统在特定细胞RNA位点的靶向m5C甲基化和去甲基化研究|项目文章
    喜讯!易基因表观转录组学RNA-BS技术服务见刊《核酸研究》大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。2024年2月15日,吉林大学张涛、赵飞宇、李金泽为共同第一作者,吉林大学李占军、隋婷婷及赖良学为共同通讯在《NucleicAcidsResearch》(NAR/IF14.9)发表题为“Pro......
  • P1156 垃圾陷阱
    原题链接题解太妙了如果能出去,那么出去的时间一定为让我出去的那个垃圾掉落的时间,且在此之前我所在的高度能撑到我垃圾掉落如果出不去,我肯定一直呆在井底不动所以我们可以以高度为变量设每个高度能撑到的最久的时间而每个垃圾在拿到的一瞬间要么吃要么搭,所以我们穷举,两个都......
  • AI智能分析网关V4智慧环保/智慧垃圾站视频智能分析与监控方案
    一、背景介绍随着城市化进程的加速,垃圾处理问题日益受到人们的关注,传统的垃圾站管理方式已经无法满足现代社会的需求。针对当前垃圾站的监管需求,TSINGSEE青犀可基于旗下视频智能检测AI智能分析网关V4与安防监控视频综合管理系统EasyCVR平台,打造智慧垃圾站视频监控与智能分析方案......
  • SiteServer CMS远程模板下载getshell漏洞导致的黑SEO利用分析溯源
    前言某日中午,涉及一代理商客户网站发现异常SQ内容,要求进行溯源分析并找出根本原因。0x01初步分析通过提供的链接(www.xxx.com.cn/2023j19tPLKn2/55151),确认涉及黑帽SEO活动,通过百度搜索进一步验证也证实了这一点。0x02日志分析黑客常常在植入菠菜或非法广告的网站中设置后......
  • 内存与垃圾回收篇之(四)程序计数器
    程序计数器(PC寄存器)1.PCRegister介绍​ JVM中的程序计数寄存器(ProgramCounterRegister)中,Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。​ 这里,并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数......