CMS垃圾回收器详解

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。

从名字中的Mark Sweep这两个词可以看出,CMS收集器是一种 “标记-清除”算法实现的,它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤:

  • 初始标记(CMS initial mark)
  • 并发标记(CMS concurrent mark)
  • 重新标记(CMS remark)
  • 并发清理(CMS concurrent sweep)

其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是枚举全部的GC Roots对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程【采用三色标记算法】,这个过程耗时较长但是不需要停顿用户线程, 可以与垃圾收集线程一起并发运行。因为用户程序继续运行,可能会有导致已经标记过的对象状态发生改变。而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。并发清理这个阶段、清理删除掉标记阶段判断已经死亡的对象,由于不需要移动存活对象,因此这个阶段可以与用户线程同时发生。

初始标记:迄今为止在进行根节点枚举这一步骤都是需要暂停用户线程的,必须要保证在一个能够保证一致性的快照中得以进行。这里的一致性指的是,不会出现在分析过程中,根节点集合的对象的引用关系还在不断地变化。因为如果这点不能满足,那么分析结果就不能保证。

那么对于目前的Java应用来说,光是方法区的大小就有数百上千兆,里面的类或者常量更是恒河数沙,若是检查这里为起源的引用就需要消耗很多的时间,所以虚拟机自当是有办法直接得到哪些地方存在着对象的引用。在HotSpot虚拟机中,是使用的一组称为OopMap的数据结构来达存放这些引用。一旦类加载完成的时候,虚拟机就会把对象的偏移量数据计算出来。并且在JIT即时编译中也会在特定的位置记录下栈里的寄存器中存放哪些位置是引用。这样收集器在扫描的时候就可以得知这些信息了。并不需要真正的一个不漏的从方法区等GCROOT开始查找。

从它的名字就可以看出它是一款优秀的垃圾收集器,主要优点:并发收集、低停顿。但是它有下面几个明显的缺点:

  • 对CPU资源敏感(会和服务抢资源,降低吞吐量);当然,这是所有并发收集器的缺点
  • 无法处理浮动垃圾(在并发标记和并发清理阶段又产生垃圾,这种浮动垃圾在本次收集中无法干掉他们,只能等到下一次gc再清理了,这一部分垃圾成为浮动垃圾);
  • 它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生

同样由于垃圾收集阶段用户程序还需要持续运行,那就还需要预留足够的空间给用户线程使用,因此CMS垃圾回收器不能像其他的收集器那样等待老年代几乎完全被填满在进行垃圾收集。如果CMS运行期间预留的内存无法满足程序分配新对象的空间,就会出现并发失败。这时候虚拟机就启动默认的备预案,冻结用户线程,临时启用·重新对老年代的垃圾收集。这样就导致停顿时间很长了,性能反而降低。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值