并发的标记—清除(Concurrent Mark Sweep,缩写为 CMS)收集器,使得在整个收集的过程中只是很短的暂停应用的执行,可通过在 JVM 参数中设置-XX:UseConcMarkSweepGC 来使用此收集器,不过此收集器仅用于old和Perm(永生)的对象收集,并发的标记—清除较之Stop-The-World 的标记—清除复杂了很多,来看看:

  并发标记—清除做到的是在标记访问每一个节点时以及清除不活跃的对象时采用和应用并发的方式,仅需在初始化标记节点状态以及最终标记节点状态时需要暂停整个应用,因此其造成的应用的暂停的时间会比较的短。

  并发标记—清除为了保证尽量短的造成应用的暂停,首先从分配内存上做了改动,CMS提供了两个 free lists,一个用于存放小对象,另外一个则用于存放大对象,当 JVM 需要给对象分配内存时,则通过 free list 来找到可用的堆地址,并进行内存的分配以及将此地址从 free
list 删除,当 CMS 回收对象内存后,则将其相应的地址重新放入此 free list 中,这样的好处是在回收对象的时候不需要做对象的移动等,因此可以让回收过程并发的进行。

  接着来看看并发标记—清除的执行步骤:

1.Initial Marking --初始标记
  此步需要暂停整个应用,JVM 扫描整个 old generation 中根对象可直接访问到的对象,并对这些对象进行标记,对于标记的对象 CMS 采用一个外部的 bit 数组来进行记录。

2. Concurrent Marking --并发标记
  在初始化标记完毕后,CMS 恢复所有应用的线程,同时开始并发的对之前标记过的对象进行轮循,以标记这些对象可访问的对象。CMS 为了确保能够扫描到所有的对象,避免在 Initial Marking 中还有未标识到的对象,采用的方法为找到标记了的对象,并将这些对象放入 Stack 中,扫描时寻找此对象依赖的对象,如果依赖的对象的地址在其之前,则将此对象进行标记,并同时放入 Stack 中,如依赖的对象地址在其之后,则仅标记该对象。

  在进行 Concurrent Marking 时 minor GC 也可能会同时进行,这个时候很容易造成旧生代对象引用关系改变,CMS 为了应对这样的并发现象,提供了一个 Mod Union Table 来进行记录,在这个 Mod Union Table 中记录每次 minor GC 后修改了的 Card 的信息。

  在进行 Concurrent Marking 时还有可能会出现的一个并发现象是应用修改了旧生代中的对象的引用关系,CMS 中仍然采用 Card Table 的方式来进行记录,在 Card 中将某对象标识为 dirty 状态,但即使是这样仍然可能会出现一种现象导致不再被引用的对象仍然是 marked的状态:

3.Final Marking -- 最终标记
  此步需要暂停整个应用,由于在 Concurrent Marking 时应用可能会修改对象的引用关系或创建新的对象,因此需要把这些改变或新创建的对象也进行扫描,CMS 递归扫描 Mod Union Table 以及 Card Table 中 dirty 的对象,并进行标记。

4.Concurrent Sweeping -- 并发清除
  在完成了 Final Marking 后,恢复所有应用的线程,就进入到这步了,这步需要负责的是将没有标记的对象进行回收。

  回收过程是并发进行的,而 JVM 分配对象内存(尽管 CMS 仅用于 old generation,但有些时候会由于应用创建的对象过大导致直接分配到 old generation 的现象,另外一种现象就是 young generation 经过回收后需要转入 old generation 的对象)和 CMS 释放内存又都是操
作 free list,会产生 free list 竞争的现象,因此 CMS 在此增加了 Mutual exclusion locks,以 JVM分配优先。

  CMS 为了避免每次回收后回收到的大小都比之前分配出去的内存小,在进行 sweeping的时候,还会尽量的将相邻的块重新组装为一个块,sweeping 为了避免和 JVM 分配对象内存产生冲突,采用的方法为首先从 free list 中删除块,组装完毕后再重新放入块中,为了能够从 free list 中删除指定的块,CMS 将 free list 设计为了双向链表。

总结:

  CMS 中的耗时的过程都是和应用并发进行的,这也是 CMS 最突出的优点,使得其造成的应用的暂停时间比 Mark-Sweeping 的方式短了很多,但同时也意味着 CMS 会和应用线程争抢 CPU 资源, CMS 回收内存的方式也使得其很容易产生内存碎片,降低了空间的利用率,
另外就是 CMS 在回收时容易产生一些应该回收但需要等到下次 CMS 才能被回收掉的对象,例如上图中的 C 对象,称为“浮动垃圾“,这也就要求了采用 CMS 的情况下需要提供更多的可用的旧生代空间,总体来说 CMS 很适用于对响应时间要求很高、CPU 资源竞争不是很激烈以及内存空间相对更充足的系统。

  MS 为了降低和应用争抢 CPU 资源的现象发生,还提供了一种增量的模式,称为 i-CMS,在这种模式下,CMS 仅启动一个处理器线程来并发的扫描标记和清除,并且该线程在执行一小段时间后就会先将 CPU 使用权让出来,分多次多段的方式来完成整个扫描标记和清除
的过程,这样降低了对于 CPU 资源的消耗,但同时也降低了 CMS 的性能,因此仅适用于 CPU少的应用。
  CMS 为了减少产生的内存碎片,提高 jvm 空间的利用率,提供了一个整理碎片的功能,可通过在 jvm 中指定-XX:+ UseCMSCompactAtFullCollection (开启对内存空间的整理工作)来启动此功能,在启动了此功能后默认为每次 Full GC 的时候都会进行整理,也可以通过-XX:CMSFullGCsBeforeCompaction=来指定多少次 Full GC 后才执行整理,不过要注意的是,整理这个步骤是需要暂停整个应用的。

[-->  注 <--]

  Mod Union Table ----在并发标记阶段Minor GC 造成的对象之间引用的变化

  Card Table --- 在并发标记阶段应用程序本身造成对象之间引用的变化。

JVM -- CMS的更多相关文章

  1. JVM CMS 常用参数配置(修订)

    搜集到的一些参数内容,比较有用,大部分转载自并发编程网ifeve.com. -XX:+UseConcMarkSweepGC该标志首先是激活CMS收集器.默认HotSpot JVM使用的是并行收集器. ...

  2. jvm——CMS 垃圾回收器(未完)

    https://matt33.com/2018/07/28/jvm-cms/ 阶段1:Initial Mark stop-the-wolrd 标记那些直接被 GC root 引用或者被年轻代存活对象所 ...

  3. JVM日志和参数的理解

    写这篇wiki的目的:最近在调整Hbase的JVM,翻了些文档和wiki,想写点东西,给自己和想了解jvm日志和参数的同 学提供些帮助. 一:理解GC日志格式,读GC日志的方法 1:开启日志 -ver ...

  4. 【GoLang】golang垃圾回收 & 性能调优

    golang垃圾回收 & 性能调优 参考资料: 如何监控 golang 程序的垃圾回收_Go语言_第七城市 golang的垃圾回收(GC)机制 - 两只羊的博客 - 博客频道 - CSDN.N ...

  5. Java内存溢出优化性能优化

    高性能应用构成了现代网络的支柱.LinkedIn有许多内部高吞吐量服务来满足每秒数千次的用户请求.要优化用户体验,低延迟地响应这些请求非常重要. 比如说,用户经常用到的一个功能是了解动态信息——不断更 ...

  6. 【JAVA】JAVA相关知识点收集

    下面这些链接都是我这段时间(7月-9月)看过的.感觉自己现在处于一个疯狂吸收知识的阶段,如果是文字的方式一点一点搬运到自己的博客既重复又费时间,只有等自己积累到一定程度后才能进行原创性高质量的产出吧. ...

  7. JVM GC算法 CMS 详解(转)

    前言 CMS,全称Concurrent Low Pause Collector,是jdk1.4后期版本开始引入的新gc算法,在jdk5和jdk6中得到了进一步改进,它的主要适合场景是对响应时间的重要性 ...

  8. JVM实用参数(七)CMS收集器

    HotSpot JVM的并发标记清理收集器(CMS收集器)的主要目标就是:低应用停顿时间.该目标对于大多数交互式应用很重要,比如web应用.在我们看一下有关JVM的参数之前,让我们简要回顾CMS收集器 ...

  9. UseAdaptiveSizePolicy与CMS垃圾回收同时使用导致的JVM报错

    系统在灰度环境上变更时发现JVM启动报错,详细检查JVM配置参数,发现新境了如下配置: -XX:+UseAdaptiveSizePolicy和-XX:+UseConcMarkSweepGC 初步猜想是 ...

随机推荐

  1. jmeter 通过ant集成到jenkins

    jmeter可以通过ant自动执行测试脚本,然后集成到jenkins上,并发送测试报告 1.下载安装ant 2.将jmeter安装包extras文件夹里ant-jemter-1.1.1.jar 复制到 ...

  2. windows下安装MySQLdb模块

    从http://www.codegood.com/downloads 下载mysqldb相应的exe文件直接安装. 我用的是MySQL-python-1.2.3.win32-py2.7.exe

  3. [转]深度探索C语言函数可变长参数

    转自:http://www.cnblogs.com/chinazhangjie/archive/2012/08/18/2645475.html 一.基础部分 1.1 什么是可变长参数 可变长参数:顾名 ...

  4. angularjs学习总结(快速预览版)

    对html标签的增强 -> 指令 指令的本质是什么 声明的方式调用相应的脚本,实现一些操作,声明的所在的dom就是脚本的执行上下文? 自定义标签 -- 标签指令自定义属性 -- 属性指令特定格式 ...

  5. Delphi程序自删除的几种方法

    program Project1; uses SysUtils, windows; var f:textfile; a:string; begin a:=paramstr(); assignfile( ...

  6. HDU 3802 Ipad,IPhone

    http://wutyyzchangde.blog.163.com/blog/static/172226566201132311311374/ #include <cstdio> type ...

  7. TMT行业分析师

    诚聘英才 - 传媒梦工场 TMT行业分析师 工作经验:  2年以上 发布日期:  2013-01-04 最低学历:  本科 管理经验:  否 工作性质:  全职 招聘人数:  1人 职位类别:  金融 ...

  8. CTreeCtrl 控件使用总结

    一 基础操作  1 插入节点 1)插入根节点 [cpp] view plaincopy //插入根节点 HTREEITEM hRoot; CString str=L"ROOT" h ...

  9. 【SqlServer数据类型、C#数据类型、SqlDbType】对应关系及转换

    // sql server数据类型(如:varchar)// 转换为SqlDbType类型public static SqlDbType SqlTypeString2SqlType(string sq ...

  10. 【转】利用Ajax.BeginForm提交文件

    Ajax.BeginForm @using (Ajax.BeginForm("YourAction", "YourController", new AjaxOp ...