专注于Java领域优质技术,欢迎关注
作者:javaadu
引子带着问题去学习一个东西,才会有目标感,我先把一直以来自己对CMS的一些疑惑罗列了下,希望这篇学习笔记能解决掉这些疑惑,希望也能对你有所帮助。
CMS出现的初衷、背景和目的?CMS的适用场景?CMS的trade-off是什么?优势、劣势和代价CMS会回收哪个区域的对象?CMS的GC Roots包括那些对象?CMS的过程?CMS和Full gc是不是一回事?CMS何时触发?CMS的日志如何分析?CMS的调优如何做?CMS扫描那些对象?CMS和CMS collector的区别?CMS的推荐参数设置?为什么ParNew可以和CMS配合使用,而Parallel Scanvenge不可以?一、基础知识CMS收集器:Mostly-Concurrent收集器,也称并发标记清除收集器(Concurrent Mark-Sweep GC,CMS收集器),它管理新生代的方式与Parallel收集器和Serial收集器相同,而在老年代则是尽可能得并发执行,每个垃圾收集器周期只有2次短停顿。我之前对CMS的理解,以为它是针对老年代的收集器。今天查阅了《Java性能优化权威指南》和《Java性能权威指南》两本书,确认之前的理解是错误的。CMS的初衷和目的:为了消除Throught收集器和Serial收集器在Full GC周期中的长时间停顿。CMS的适用场景:如果你的应用需要更快的响应,不希望有长时间的停顿,同时你的CPU资源也比较丰富,就适合适用CMS收集器。二、CMS的过程CMS的正常过程
这里我们首先看下CMS并发收集周期正常完成的几个状态。
(STW)初始标记:这个阶段是标记从GcRoots直接可达的老年代对象、新生代引用的老年代对象,就是下图中灰色的点。这个过程是单线程的(JDK7之前单线程,JDK8之后并行,可以通过参数CMSParallelInitialMarkEnabled调整)。
初始标记标记的对象
并发标记:由上一个阶段标记过的对象,开始tracing过程,标记所有可达的对象,这个阶段垃圾回收线程和应用线程同时运行,如上图中的灰色的点。在并发标记过程中,应用线程还在跑,因此会导致有些对象会从新生代晋升到老年代、有些老年代的对象引用会被改变、有些对象会直接分配到老年代,这些受到影响的老年代对象所在的card会被标记为dirty,用于重新标记阶段扫描。这个阶段过程中,老年代对象的card被标记为dirty的可能原因,就是下图中绿色的线:
并发标记过程中受到影响的对象
预清理:预清理,也是用于标记老年代存活的对象,目的是为了让重新标记阶段的STW尽可能短。这个阶段的目标是在并发标记阶段被应用线程影响到的老年代对象,包括:(1)老年代中card为dirty的对象;(2)幸存区(from和to)中引用的老年代对象。因此,这个阶段也需要扫描新生代 老年代。【PS:会不会扫描Eden区的对象,我看源代码猜测是没有,还需要继续求证】
预清理中扫描from和to区
可中断的预清理:这个阶段的目标跟“预清理”阶段相同,也是为了减轻重新标记阶段的工作量。可中断预清理的价值:在进入重新标记阶段之前尽量等到一个Minor GC,尽量缩短重新标记阶段的停顿时间。另外可中断预清理会在Eden达到50%的时候开始,这时候离下一次minor gc还有半程的时间,这个还有另一个意义,即避免短时间内连着的两个停顿,如下图资料所示:
避免连续停顿的发生
在预清理步骤后,如果满足下面两个条件,就不会开启可中断的预清理,直接进入重新标记阶段:
Eden的使用空间大于“CMSScheduleRemarkEdenSizeThreshold”,这个参数的默认值是2M;Eden的使用率大于等于“CMSScheduleRemarkEdenPenetration”,这个参数的默认值是50%。如果不满足上面两个条件,则进入可中断的预清理,可中断预清理可能会执行多次,那么退出这个阶段的出口有两个(源码参见下图):
设置了CMSMaxAbortablePrecleanLoops,并且执行的次数超过了这个值,这个参数的默认值是0; CMSMaxAbortablePrecleanTime,执行可中断预清理的时间超过了这个值,这个参数的默认值是5000毫秒。
可中断预清理退出的条件
如果是因为这个原因退出,gc日志打印如下:
可中断预清理由于时间退出
有可能可中断预清理过程中一直没等到Minor gc,这时候进入重新标记阶段的话,新生代还有很多活着的对象,就回导致STW变长,因此CMS还提供了CMSScavengeBeforeRemark参数,可以在进入重新标记之前强制进行依次Minor gc。
(STW)重新标记:重新扫描堆中的对象,进行可达性分析,标记活着的对象。这个阶段扫描的目标是:新生代的对象 Gc Roots 前面被标记为dirty的card对应的老年代对象。如果预清理的工作没做好,这一步扫描新生代的时候就会花很多时间,导致这个阶段的停顿时间过长。这个过程是多线程的。并发清除:用户线程被重新激活,同时将那些未被标记为存活的对象标记为不可达;并发重置:CMS内部重置回收器状态,准备进入下一个并发回收周期。CMS的异常情况上面描述的是CMS的并发周期正常完成的情况,但是还有几种CMS并发周期失败的情况:
并发模式失败(Concurrent mode failure):CMS的目标就是在回收老年代对象的时候不要停止全部应用线程,在并发周期执行期间,用户的线程依然在运行,如果这时候如果应用线程向老年代请求分配的空间超过预留的空间(担保失败),就回触发concurrent mode failure,然后CMS的并发周期就会被一次Full GC代替——停止全部应用进行垃圾收集,并进行空间压缩。如果我们设置了UseCMSInitiatingOccupancyOnly和CMSInitiatingOccupancyFraction参数,其中CMSInitiatingOccupancyFraction的值是70,那预留空间就是老年代的30%。晋升失败:新生代做minor gc的时候,需要CMS的担保机制确认老年代是否有足够的空间容纳要晋升的对象,担保机制发现不够,则报concurrent mode failure,如果担保机制判断是够的,但是实际上由于碎片问题导致无法分配,就会报晋升失败。永久代空间(或Java8的元空间)耗尽,默认情况下,CMS不会对永久代进行收集,一旦永久代空间耗尽,就回触发Full GC。三、CMS的调优针对停顿时间过长的调优 首先需要判断是哪个阶段的停顿导致的,然后再针对具体的原因进行调优。使用CMS收集器的JVM可能引发停顿的情况有:(1)Minor gc的停顿;(2)并发周期里初始标记的停顿;(3)并发周期里重新标记的停顿;(4)Serial-Old收集老年代的停顿;(5)Full GC的停顿。其中并发模式失败会导致第(4)种情况,晋升失败和永久代空间耗尽会导致第(5)种情况。针对并发模式失败的调优想办法增大老年代的空间,增加整个堆的大小,或者减少年轻代的大小以更高的频率执行后台的回收线程,即提高CMS并发周期发生的频率。设置UseCMSInitiatingOccupancyOnly和CMSInitiatingOccupancyFraction参数,调低CMSInitiatingOccupancyFraction的值,但是也不能调得太低,太低了会导致过多的无效的并发周期,会导致消耗CPU时间和更多的无效的停顿。通常来讲,这个过程需要几个迭代,但是还是有一定的套路,参见《Java性能权威指南》中给出的建议,摘抄如下:对特定的应用程序,该标志的更优值可以根据 GC 日志中 CMS 周期首次启动失败时的值得到。具体方法是,在垃圾回收日志中寻找并发模式失效,找到后再反向查找 CMS 周期最近的启动记录,然后根据日志来计算这时候的老年代空间占用值,然后设置一个比该值更小的值。增多回收线程的个数CMS默认的垃圾收集线程数是(CPU个数 3)/4,这个公式的含义是:当CPU个数大于4个的时候,垃圾回收后台线程至少占用25%的CPU资源。举个例子:如果CPU核数是1-4个,那么会有1个CPU用于垃圾收集,如果CPU核数是5-8个,那么久会有2个CPU用于垃圾收集。
针对永久代的调优
如果永久代需要垃圾回收(或元空间扩容),就会触发Full GC。默认情况下,CMS不会处理永久代中的垃圾,可以通过开启CMSPermGenSweepingEnabled配置来开启永久代中的垃圾回收,开启后会有一组后台线程针对永久代做收集,需要注意的是,触发永久代进行垃圾收集的指标跟触发老年代进行垃圾收集的指标是独立的,老年代的阈值可以通过CMSInitiatingPermOccupancyFraction参数设置,这个参数的默认值是80%。开启对永久代的垃圾收集只是其中的一步,还需要开启另一个参数——CMSClassUnloadingEnabled,使得在垃圾收集的时候可以卸载不用的类。
四、CMS的trade-off是什么?优势
低延迟的收集器:几乎没有长时间的停顿,应用程序只在Minor gc以及后台线程扫描老年代的时候发生极其短暂的停顿。劣势
更高的CPU使用:必须有足够的CPU资源用于运行后台的垃圾收集线程,在应用程序线程运行的同时扫描堆的使用情况。【PS:现在服务器的CPU资源基本不是问题,这个点可以忽略】CMS收集器对老年代收集的时候,不再进行任何压缩和整理的工作,意味着老年代随着应用的运行会变得碎片化;碎片过多会影响大对象的分配,虽然老年代还有很大的剩余空间,但是没有连续的空间来分配大对象,这时候就会触发Full GC。CMS提供了两个参数来解决这个问题:(1)UseCMSCompactAtFullCollection,在要进行Full GC的时候进行内存碎片整理;(2)CMSFullGCsBeforeCompaction,每隔多少次不压缩的Full GC后,执行一次带压缩的Full GC。会出现浮动垃圾;在并发清理阶段,用户线程仍然在运行,必须预留出空间给用户线程使用,因此CMS比其他回收器需要更大的堆空间。五、几个问题的解答为什么ParNew可以和CMS配合使用,而Parallel Scanvenge不可以?
答:这个跟Hotspot VM的历史有关,Parallel Scanvenge是不在“分代框架”下开发的,而ParNew、CMS都是在分代框架下开发的。
CMS中minor gc和major gc是顺序发生的吗?
答:不是的,可以交叉发生,即在并发周期执行过程中,是可以发生Minor gc的,这个找个gc日志就可以观察到。
CMS的并发收集周期合适触发?
由下图可以看出,CMS 并发周期触发的条件有两个:
触发cms并发周期的条件
阈值检查机制:老年代的使用空间达到某个阈值,JVM的默认值是92%(jdk1.5之前是68%,jdk1.6之后是92%),或者可以通过CMSInitiatingOccupancyFraction和UseCMSInitiatingOccupancyOnly两个参数来设置;这个参数的设置需要看应用场景,设置得太小,会导致CMS频繁发生,设置得太大,会导致过多的并发模式失败。例如
动态检查机制:JVM会根据最近的回收历史,估算下一次老年代被耗尽的时间,快到这个时间的时候就启动一个并发周期。设置UseCMSInitiatingOccupancyOnly这个参数可以将这个特性关闭。
CMS的并发收集周期会扫描哪些对象?会回收哪些对象?
答:CMS的并发周期只会回收老年代的对象,但是在标记老年代的存活对象时,可能有些对象会被年轻代的对象引用,因此需要扫描整个堆的对象。
CMS的gc roots包括哪些对象?
答:首先,在JVM垃圾收集中Gc Roots的概念如何理解(参见R大对GC roots的概念的解释);第二,CMS的并发收集周期中,如何判断老年代的对象是活着?我们前面提到了,在CMS的并发周期中,仅仅扫描Gc Roots直达的对象会有遗漏,还需要扫描新生代的对象。如下图中的蓝色字体所示,CMS中的年轻代和老年代是分别收集的,因此在判断年轻代的对象存活的时候,需要把老年代当作自己的GcRoots,这时候并不需要扫描老年代的全部对象,而是使用了card table数据结构,如果一个老年代对象引用了年轻代的对象,则card中的值会被设置为特殊的数值;反过来判断老年代对象存活的时候,也需要把年轻代当作自己的Gc Roots,这个过程我们在第三节已经论述过了。
老年代和新生代互相作为Gc Roots
如果我的应用决定使用CMS收集器,推荐的JVM参数是什么?我自己的应用使用的参数如下,是根据PerfMa的xxfox生成的,大家也可以使用这个产品调优自己的JVM参数:
CMS相关的参数总结(需要注意的是,这里我没有考虑太多JDK版本的问题,JDK1.7和JDK1.8这些参数的配置,有些默认值可能不一样,具体使用的时候还需要根据具体的版本来确认怎么设置)
常见的cms主要有哪些(这应该是全网最全的CMS学习笔记了)
2024-11-06 07:15:22 作者:半夜床丄戲 网址:https://m.xinb2b.cn/tech/reh432017.html
- 适合男孩过生日的句子有哪些(适合男孩过生日的句子有什么)
- 2024-11-06适合男孩过生日的句子有什么祝你生日快乐,永远都幸福仰首看见康庄大道在面前,俯首看见金银铺满地!!站好队,排成排,大家齐给你道喜来,今天你是寿星佬,只是胡子没能长出来大家都把礼物送,我送短信表情怀,祝你年年都康健,祝你天天都开怀。
- 牛肉如何炒又嫩又香(不同部位的牛肉都应该怎么吃)
- 2024-11-06不同部位的牛肉都应该怎么吃牛肉,最常见的肉类之一因其瘦肉率高,味道独特,营养丰富,深受大众喜爱牛肉中含有丰富的蛋白质和各种氨基酸氨基酸,能为人体生长发育提供大量营养,还能能提高机体抵抗力,对术后病人在身体调养方面也有很好的辅助。
- 发动机混合气过浓怎么导致的(怎样解决汽车发动机混合气)
- 2024-11-06怎样解决汽车发动机混合气很多汽车开了一段时间后,会出现“回火”或者“放炮”的现象,这是咋回事?一般而言出现这两种情况就表明混合气出问题了混合气过稀会“回火”,过浓又容易“放炮”,怎样解决发动机混合气过浓或过稀的问题呢?一起来。
- 红烧老干妈排骨家常做法(老干妈蒸排骨做法超级受欢迎的家常菜)
- 2024-11-06老干妈蒸排骨做法超级受欢迎的家常菜做法1.将排骨段洗净放入盘中备用2.葱姜蒜切片,香菜切沫3.倒入10克油,放入豆瓣酱,大火炒出红油,放入葱姜蒜爆香4.加入料酒,放老干妈炒匀,再加入蚝油、鸡粉、胡椒粉、味精、生抽、白糖、南乳汁,炒匀,。
- 英雄联盟手游炸弹人出装和符文(英雄联盟手游炸弹人)
- 2024-11-06英雄联盟手游炸弹人最近和我朋友双排了一把,他也算是半个新手了,S5就没有玩LOL了,也没玩过啥王者等手游,跟他玩了一下手游双排,炸弹人石头人,纯是简单又粗暴,白金到翡翠的局面,他不太会玩儿,输出不是第一,就是炸弹人玩的。
- 丁泽仁站姐进局子了吗(站姐花300万还被多方威胁)
- 2024-11-06站姐花300万还被多方威胁杜华选艺人的第一要素就是身高颜值都要高,有了这两点,加上团队的栽培,一般实力也不会差到哪里去,虽然整体来说,乐华艺人的整体文化水平不高,毕竟小小年纪就进公司,哪还有什么时间学习当初《偶像练习生》的开播。
- 森林游戏作弊码上帝模式(stesm游戏森林怎么用作弊码)
- 2024-11-06stesm游戏森林怎么用作弊码森林作为一款单机游戏,那么作弊码就成为了必不可少的存在,但是相信肯定还有很多玩家不知道怎么用,下面给大家大概说一下方法首先登录游戏,在大厅界面用英文输入法输入developermodeon然后点击回车。
- 白带都有哪些状态(一分钟了解白带)
- 2024-11-06一分钟了解白带白带在医学上被称为阴道分泌物包含有宫颈分泌的黏液阴道黏膜的渗出物前庭大腺分泌的黏液子宫颈和阴道脱落的表皮细胞还可能混合了少量子宫内膜腺体的分泌物以及少量的白细胞和非致病性阴道杆菌等正常的白带是什么状态。
- 翡翠检测费用是多少钱(翡翠检测费用需要多少钱)
- 2024-11-06翡翠检测费用需要多少钱翡翠鉴定的费用并不高,据悉,翡翠市场的源头,单次鉴定的费用大概在几十元左右广东平洲、揭阳、四会作为玉器批发市场的源头,当地有许多权威的鉴定检测机构,倘若在平洲与当地鉴定机构合作,国检的翡翠证书的会员价。
- 自动洗手机怎么加洗手液 几素智能自动洗手机
- 2024-11-06自动洗手机怎么加洗手液 几素智能自动洗手机小时候家长、老师甚至电视都教育我们,饭前要洗手,饭后要漱口最近两年众所周知的经历让大家有了新的常识:勤洗手常通风戴口罩洗手是每天都要做n遍的事情,今天给大家介绍一款几素出品的智能自动洗手机日常生活中,。
- 坦克新兵下连队是怎样分配的 参加二战坦克考卷
- 2024-11-06坦克新兵下连队是怎样分配的 参加二战坦克考卷《重装集结:二战》即将迎来内测在期待之余我们做了份二战坦克知识考卷不知道你们能答对几道呢?一起来测测吧!Part.01——点击查看答案——▼Part.02——点击查看答案——▼Part.03——点击查。
- 青岛北站始发高铁车次(青岛西站已开售重庆)
- 2024-11-06青岛西站已开售重庆自2019年12月30日零时起,全国铁路将执行新的列车运行图记者从铁路部门获悉,青岛站、青岛北站共新增始发列车20趟,青岛西站新增停靠列车18趟调图后青岛西站图定旅客列车由47趟调整为57趟目前,青岛。