CMS收集器
CMS全称
Concurrent Mark Sweep
,是一款并发的、主要使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,在初始化阶段会导致STW。
-
这里有一个
重点
: 主要标记-清除算法的垃圾回收器
不是标记-整理算法 -> 说明会出现很多内存间隙,也就是内存碎片,有解决办法- 如果并发的时候内存不够新对象产生,就会并发失败,虚拟机会被迫临时启用
单线程的serial old垃圾回收器
来回收老年代的垃圾 - 还有一个参数配置,多次FullGC后,下次FullGC会先执行一段
标记-整理算法
- 如果并发的时候内存不够新对象产生,就会并发失败,虚拟机会被迫临时启用
-
不再推荐使用CMS收集器
的最大原因是: 出现了G1收集器,完善了它的一些缺陷,官方给他打上了不推荐的标记- 实际上可能CMS还是用的最多的,大家都是JDK 8
CMS描述
- CMS收集器说的是
新生代的ParNew收集器
和老年代的CMS收集器
的结合体 - 不管是ParNew收集器还是以前被淘汰的Serial和Parallel的收集器,有个非常严重的问题
- 就是在ParNew这些收集器线程开始运行的时候,其他
所有线程全部暂停
,直到GC线程走完 - 这些收集器线程甚至都不能跟其他线程共存,有你没我
- 就是在ParNew这些收集器线程开始运行的时候,其他
- 而CMS在新生代依然使用了ParNew收集器,在老年代使用
新的CMS收集器
,可以跟其他线程并发运行- 这里并不是说就不会出现STW了丶其他线程不会在暂停了,并不是
- 是在
需要暂停的时候暂停一小段时间
,其他时候线程大家可以共存,这会带来肉眼可见的提升
至今为止,所有垃圾收集器都不能防止STW的产生
,只能降低STW的暂停时间来优化垃圾回收效率第一次
实现了让垃圾收集线程与用户线程(基本上)同时工作
CMS应用场景
-
出现在:
一切卡顿就让你崩溃
的应用程序!!!- APP点着点着就
无缘无故你都不知道怎么回事
它就卡起来了 - 影响用户体验
- APP点着点着就
-
相对的,
可以不使用CMS的应用场景
- 你知道提交东西要停顿一下丶上传要停顿一下等等这些场景
- 理论上你知道了会卡顿,稍微卡卡,并不会太影响用户体验
CMS配置
堆内存为4G,新生代为2G,老年代也为2G
新生代采用ParNew收集器,老年代采用并发标记清除的CMS收集器
当老年代的内存占用率达到80%时会进行FullGC,并且开启碎片整理
-Xms4g -Xmx4g -Xmn2g -Xss1024K
-XX:ParallelGCThreads=5
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSInitiatingOccupancyFraction=80
CMS收集过程
注意: 这个描述的过程都是CMS在老年代的收集过程.CMS本来也就是老年代的垃圾回收器
初始标记
(CMS-initial-mark) ,会导致STW;- 标记GC Roots可达的对象,GC Roots本身和直接能引用到的对象 -> 标记的都是来自老年代的对象
- 内容不多,速度快,STW暂停实际段
并发标记
(CMS-concurrent-mark),与用户线程同时运行;- 从刚刚标记GC Roots可达的对象开始,遍历所有可达的对象
- 需要的时间长,但是此阶段可以并发运行
重新标记
(CMS-remark) ,会导致swt;- 验证修改标记,将没有标记到的标记
- 引用链有改变的标记重新分析
- 用时时间一般,比初始标记快,比并发标记慢
- 验证修改标记,将没有标记到的标记
并发清除
(CMS-concurrent-sweep),与用户线程同时运行;- 直接删掉
CMS的缺点
-
使用
标记-清除算法有碎片
,但也有解决的办法,有对应的参数开启整理 -
有浮动垃圾
: 最后一个并发清除阶段,也会有新的对象来到老年代,这些对象垃圾此时已经没办法标记了,只能等到下次 -
影响程序的整体性能
: 因为要并发执行垃圾回收,所以cpu会一直分配时间给垃圾回收线程,会一直占用一部分cpu的资源
点赞.靓仔