博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CMS垃圾收集器深入详解
阅读量:5019 次
发布时间:2019-06-12

本文共 2170 字,大约阅读时间需要 7 分钟。

上一次【】对安全点和安全区进行了理论化的了解,接下来继续对CMS进行其它理论的了解,还是纯理论!!坚持,因为下一次就会有实践代码了~~

CMS收集器

  • CMS(Concurrent Mark Sweep)收集器,以获取最短回收停顿时间【也就是指Stop The World的停顿时间】为目标,多数应用于互联网站或者B/S系统的服务器端上。其中“Concurrent”并发是指垃圾收集的线程和用户执行的线程是可以同时执行的。
  • CMS是基于“标记-清除”算法实现的,整个过程分为4个步骤:
    1、初始标记(CMS initial mark)。
    2、并发标记(CMS concurrent mark)。
    3、重新标记(CMS remark)。
    4、并发清除(CMS concurrent sweep)。
    注意:“标记”是指将存活的对象和要回收的对象都给标记出来,而“清除”是指清除掉将要回收的对象。
  • 其中,初始标记、重新标记这两个步骤仍然需要“Stop The World”。
  • 初始标记只是标记一下GC Roots能直接关联到的对象,速度很快。
  • 并发标记阶段【也就说明不会阻碍业务线程继续执行,因为它所以还会有下面要说的“重新标记”阶段了】就是进行GC Roots Tracing【啥意思?其实就是从GC Roots开始找到它能引用的所有其它对象】的过程。
  • 重新标记阶段则是为了修正并发标记期间因用户程序继续动作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。
  • CMS收集器的动作步骤如下图所示,在整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,因此,从总体上看,CMS收集器的内存回收过程是与用户线程一起并发执行的:

    下面对这个图做一个简要的解读:

    这个“重置线程"并没有体现在之前的4个步骤当中,这个在之后会说的,对于这张图的理解可以很好的理解CMS的几个步骤。 

  • 优点:并发收集、低停顿【注意:这里的停顿指的是停止用户线程】,Oracle公司的一些官方文档中也称之为并发低停顿收集器(Concurrent Low Pause Collector)。
  • 缺点:
    1、CMS收集器对CPU资源非常敏感。
    2、CMS收集器无法处理浮动垃圾(Floating Garbage,就是指在之前判断该对象不是垃圾,由于用户线程同时也是在运行过程中的,所以会导致判断不准确的, 可能在判断完成之后在清除之前这个对像已经变成了垃圾对象,所以有可能本该此垃圾被回收但是没有被回收,只能等待下一次GC再将该对象回收,所以这种对像就是浮动垃圾),可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。如果在应用中老年代增长不是太快,可能适当调高参数-XX:CMSInitiatingOccupancyFraction的值来提高触发百分比,以便降低内存回收次数从而获取更好的性能。要是CMS运行期间预留的内存无法满足程序需要时,虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。所以说参数-XX:CMSInitiatingOccupancyFraction设置得太高很容易导致大量“Concurrent Mode Failure”失败,性能反而降低。
    3、收集结束时会有大量空间碎片产生,空间碎片过多时,将会给大对象分配带来很大麻烦,往往出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前进行一次Full GC。CMS收集器提供了一个-XX:+UseCMSCompactAtFullCollection开关参数(默认就是开启的),用于在CMS收集器顶不住要进行Full GC时开启内存碎片的合并整理过程,内存整理的过程是无法并发的,空间碎片问题没有了,但停顿时间不得不变长。

空间分配担保:

在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。当大量对象在Minor GC后仍然存活,就需要老年代进行空间分配担保,把Survivor无法容纳的对象直接进入老年代。如果老年代判断到剩余空间不足(根据以往每一次回收晋升到老年代对象空间的平均值作为经验值),则进行一次Full GC。

 

CMS收集器收集完整步骤:

  • Phase1 :Initial Mark【初始标记】
  • Phase2 : Concurrent Mark 【并发标记】
  • Phase3 : Concurrent Preclean【并发预先清除】
  • Phase4 : Concurrent Abortable Preclean【并发可能失败的预先清除】
  • Phase5 : Final Remark【最终重新标记】
  • Phase6 : Concurrent Sweep【并发清除】
  • Phase7 : Concurrent Reset【并发重置】

以上这些过程在下次会详细进行学习,先有个了解。

转载于:https://www.cnblogs.com/webor2006/p/11055468.html

你可能感兴趣的文章
android ImageView网络图片加载、动态设置尺寸、圆角..
查看>>
删除github中某个文件夹
查看>>
CTF中那些脑洞大开的编码和加密
查看>>
简化工作流程 10款必备的HTML5开发工具
查看>>
c++ 调用外部程序exe-ShellExecuteEx
查看>>
Java进击C#——语法之知识点的改进
查看>>
IdentityServer流程图与相关术语
查看>>
有标号的DAG计数 II
查看>>
Redis 配置
查看>>
JavaScript常见的五种数组去重的方式
查看>>
我的fgen放到sourceforge上了
查看>>
BirdNet: a 3D Object Detection Framework from LiDAR information
查看>>
icon fonts入门
查看>>
【Django】如何按天 小时等查询统计?
查看>>
HDU2191(多重背包)
查看>>
测试用例(一)
查看>>
【转】 mysql反引号的使用(防冲突)
查看>>
转载【微信支付】jsapi支付之传参问题(使用微信官方SDK之PHP版本) V3之WxpayPubHelper 亲测有效,V3WxpayAPI_php_v3.zip版未测试,理论上也是一样的。...
查看>>
邮件中的样式问题
查看>>
AJAX 状态值与状态码详解
查看>>