【无标题】

JVM之CMS收集器介绍

背景

	CMS是在JDK1.5的时候提出的,是一款真正意义上的并发收集器,是第一次实现了让垃圾收集线程和用户线程一同工作的(并发执行)

应用

	CMS回收器因为主打跟用户线程交互,主要使用在互联网站或者B/S系统的服务器上,因为这类大多是面向C端的,也就要求必须让用户有良好的体验。

工作原理
主要分为4个阶
在这里插入图片描述

1. 初始标记阶段
a) 这个阶段只是对GC Roots能够直接(注意是直接不是间接)关联到的对象进行标记,因为是直接关联,所以一般这种对象较少,所以使用的时间较少。并且这个阶段会出现STW(吃饭的过程中喝了口水)

2.并发标记阶段

a) 这个阶段是对1阶段的完善,标记那些能够从GC Roots关联到的对象(这个时候是包括了间接引用的),所以这个时候的对象很多,所用时间也较慢,但不需要暂停用户线程(并发)

3 重新标记阶段
a) 因为在并发标记阶段的时候用户线程和垃圾回收线程是并发状态的,所以这个时期用户线程可能会产生新的一部分垃圾(相当于你妈打扫房间的时候不会认为你手上吃的东西是垃圾,但是打扫完了一会后你也吃完了,他也就变成了垃圾),这个阶段就是对在2阶段中标记改变的的对象进行重新标记。因为在2阶段过程中状态改变的对象不会很多,所以执行时间相较于1阶段慢,但是相较于2阶段,那不是快乐一点半点。
4. 并发清除阶段
最后一个阶段是对那些标记了死亡的对象进行空间释放(杀了),这个时候和用户对象一起并发执行

除了初始标记阶段以外,其他阶段都是用户线程和垃圾回收线程一起执行的。

该回收器主要采用”标记-清除”算法,先标记后清除。试想一下,为什么CMS不采用”标记-压缩”算法呢?先思考一下,后面做出回答
使用“标记-压缩”算法也就意味着没有办法避免空间碎片的产生,——>
在这里插入图片描述

上图就是具体的一部分回收以后产生的空间碎片。

思考一下CMS算法有什么弊端呢?
首先毋庸置疑肯定是会产生空间碎片,导致如果要分配的对象的空间过大, 可能会无法进行分配
其次因为他是并发执行,所以在跟用户线程一起执行的时候,会影响用户线程一定的效率(8个桃子一只猴子吃喝10个桃桃2只猴子吃是不一样的)
在二阶段中可能会产生新的垃圾(浮动垃圾),(你妈打扫房间的时候,你爸从客厅里面把吃的东西带到房间然后让垃圾留在房间里面),对于这一部分浮动垃圾CMS是无法对其进行回收的,因此如果这一部分垃圾过多,同样会导致OOM(Out Of Memory)的出现

那接下来我们先回答为什么CMS不使用“清除-压缩”算法。
首先,CMS是跟用户线程并行执行的,压缩算法要求在清理完垃圾之后要移动对象,进行整齐排列,然后这个时候用户线程在执行着,就相当于我在餐厅里面吃饭,服务员说因为新冠要进行消毒,消完毒以后竟然把我的菜和其他客户的菜重新进行排列,你说我还怎么吃?因此CMS不会使用“标记-清除”算法

下面关于CMS的一些参数的介绍

-XX:+UseCMSCompactAtFullCollection
该参数用于指定在执行玩Full GC之后对内存空间进行压缩整理,避免产生内存碎片,但是缺点是无法并发执行,所以你得让你的客户登上一阵子了。

-XX:CMSFullGCsBeforeCompaction
设置执行多少次Full GC以后对内存空间进行压缩整理

-XX:ParallelCMSThreads
设置CMS的线程数量,其中CMS默认启动线程的数量是(ParallelGCThreads+3)/4,并且ParallelGCThreads是年轻代并行收集器的线程数,当CPU比较紧张的时候,收到CMS收集器线程的影响,应用程序的性能在垃圾回首阶段可能会非常糟糕(我碗里都只剩下两块肉了,你还要抢走一块)。因为用户线程和收集线程是并发的,你多我就少,你少我就多,你快我就慢,你慢我就快。
介绍到这里就完了,如果有错误,欢迎指出。谢谢


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值