CMS垃圾收集器深入详解
上一次【https://www.cnblogs.com/webor2006/p/11048407.html】对安全点和安全区进行了理论化的了解,接下来继续对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【并发重置】
以上这些过程在下次会详细进行学习,先有个了解。
CMS垃圾收集器深入详解的更多相关文章
- G1垃圾收集器和CMS垃圾收集器 (http://mm.fancymore.com/reading/G1-CMS%E5%9E%83%E5%9C%BE%E7%AE%97%E6%B3%95.html#toc_8)
参考来源 JVM 体系架构 堆/栈的内存分配 静态和非静态方法的内存分配 CMS 回收算法 应用场景 CMS 垃圾收集阶段划分(Collection Phases) CMS什么时候启动 CMS缺点 G ...
- CMS垃圾收集器
介绍 CMS垃圾回收器的全称是Concurrent Mark-Sweep Collector,从名字上可以看出两点,一个是使用的是并发收集,第二个是使用的收集算法是Mark-Sweep.从而也可以推测 ...
- 系统批量运维管理器Fabric详解
系统批量运维管理器Fabric详解 Fabrici 是基于python现实的SSH命令行工具,简化了SSH的应用程序部署及系统管理任务,它提供了系统基础的操作组件,可以实现本地或远程shell命令,包 ...
- GridBagLayout布局管理器应用详解
http://www.cnblogs.com/kungfupanda/p/7220217.html GridBagLayout布局管理器应用详解 很多情况下,我们已经不需要通过编写代码来实现一个应用程 ...
- 实例透彻分析CMS垃圾收集器执行过程
CMS收集器收集步骤: 在上一次[https://www.cnblogs.com/webor2006/p/11055468.html]中已经对CMS的垃圾收集器有了一定的理论上的了解,其中提到了CMS ...
- java8学习之收集器用法详解与多级分组和分区
收集器用法详解: 在上次已经系统的阅读了Collector收集器的Javadoc对它已经有一个比较详细的认知了,但是!!!它毕境是只是一个接口,要使用的话还得用它的实现类,所以在Java8中有它进行了 ...
- ffmpeg播放器实现详解 - 视频显示
ffplay是ffmpeg源码中一个自带的开源播放器实例,同时支持本地视频文件的播放以及在线流媒体播放,功能非常强大. FFplay: FFplay is a very simple and port ...
- CMS垃圾收集器——重新标记和浮动垃圾的思考
<深入理解java虚拟机 第二版 JVM高级特性与最佳实践>里面提到 CMS 垃圾收集器. CMS 垃圾收集器的垃圾回收分4个步骤: 初始标记(initial mark) 有 STW 并发 ...
- 稳了!我准备了1个晚上的CMS垃圾收集器
面试官:今天还是来聊聊CMS垃圾收集器呗? 候选者:嗯啊... 候选者:如果用Seria和Parallel系列的垃圾收集器:在垃圾回收的时,用户线程都会完全停止,直至垃圾回收结束! 候选者:CMS的全 ...
随机推荐
- python的http包
http包简介 http包提供了 HTTP协议的一些功能,主要模块有: http.client --- 底层的 HTTP 协议的一些功能,可以为 urllib.request 模块所用 http. ...
- django中对数据库生成记录操作失败
在终端执行以下语句时,会发现一点效果也没有,但是在manage.py中会成功: python3 manage.py makemigrations # 仅仅是在小本本上(migrations文件夹)记录 ...
- optimizer.zero_grad()
# zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = net(i ...
- C++ trais技术 模板特化的应用
// traits 的应用 /////////////////////////////////////////// // traits template <typename T> clas ...
- CSP-S 2019图论总结
CSP-S 2019图论总结 一.最短路问题 模板 Floyd算法 void floyd() { memset(map,0x3f,sizeof(map)); for(int i=1;i<=n;i ...
- A1029 Median (25 分)
一.技术总结 最开始的想法是直接用一个vector容器,装下所有的元素,然后再使用sort()函数排序一下,再取出中值,岂不完美可是失败了,不知道是容器问题还是什么问题,就是编译没有报错,最后总是感觉 ...
- mysql8
解决navicat不能连接问题: grant all privileges on *.* to ‘root’@’%’;ALTER USER 'root'@'localhost' IDENTIFIED ...
- MSM8909中LK阶段LCM屏适配与显示流程分析(一)
1.前言 在驱动开发中,我们往往需要适配一些新的屏幕或者调试一些屏幕的参数等,对于Qualcomm的MSM8909这款SoC,当启动Android系统时,会有一个LK阶段,该阶段用来启动Linux内核 ...
- redis命令之 ----key(键)
DEL DEL key [key ...] 删除给定的一个或多个 key . 不存在的 key 会被忽略. DUMP DUMP key 序列化给定 key ,并返回被序列化的值,使用 RESTORE ...
- ElasticSearch 6.7.1操作纪录
以下操作均在 6.7.1版本中正常 c# ES客户端 测试项目地址:https://gitee.com/dhclly/IceDog.ElasticSearchClient/tree/master/sr ...