Concurrent Mark and Sweep

优点:大量的工作听过并发线程处理,不需要stop-the-world

缺点:老年代碎片多且在某些情况下暂停时间不可预测,特别是大型堆栈。

启用参数:

-XX:+UseConcMarkSweepGC

主要目的是:

减少GC时间,因为要抢占多大多数的cpu时间或全部cpu时间,所以应用的吞吐量相对于在Parallel GC会小。

并发标记清除算法:在Young Generation使用的是并行mark-copy且stop-the-world算法;在Old Generation使用的是大多数的并发mark-sweep算法。为了防止长时间的暂停在Old Generation:第一、不压缩而是使用free-list管理空闲空间;第二、并发执行mark-sweep,不会stop-the-world,但也是会与应用竞争CPU时间;

默认执行并发垃圾收集的线程数为 ( 并行垃圾收集线程数 + 3 )/ 4

并发线程数量

-XX:+ConcGCThreads=

启用并发标记清除算法

-XX:+UseConcMarkSweepGC

查看线程的核数命令:

java -XX:+PrintFlagsFinal -version | grep ParallelGCThreads

1:GC触发时间戳
2:GC触发时间,相对于JVM启动的时间,单位是秒
3:GC区分标志,区分是Minor GC和Full GC,这里是Minor GC
4:GC触发原因,这里是Young Generation空间不足
5:区分使用的收集器,ParNew表示在Young Generation使用的是mark-copy且stop-the-world的收集器,与Old Generation中的Concurrent Mark & Sweep 收集器一同工作
6:Young Generation在GC前后的对象占用空间大小
7:Young Generation总的空间大小
8:没有最终清理垃圾对象的GC持续时间
9:堆收集前后对象数据占用的空间大小
10:堆的总的空间大小
11:在Young Generation执行mark-copy收集器的持续时间,单位为秒,包括与ConcurrentMarkSweep通信的时间、足够老的对象提升到老年代的时间、一些最终清理的时间。
12:-user:GC占用CPU时间
        -sys:GC系统调用的时间或等待系统事件的时间
        -real:应用挂起时间,实际值会超出(user time + sys time)/垃圾收集使用到的线程数,会超出是因为有些操作是非并行化的。

Full GC

2015-05-26T16:23:07.321-0200: 64.425: [GC (CMS Initial Mark) [1 CMS-initial-mark: 10812086K(11901376K)] 10887844K(12514816K), 0.0001997 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2015-05-26T16:23:07.321-0200: 64.425: [CMS-concurrent-mark-start]
2015-05-26T16:23:07.357-0200: 64.460: [CMS-concurrent-mark: 0.035/0.035 secs] [Times: user=0.07 sys=0.00, real=0.03 secs]
2015-05-26T16:23:07.357-0200: 64.460: [CMS-concurrent-preclean-start]
2015-05-26T16:23:07.373-0200: 64.476: [CMS-concurrent-preclean: 0.016/0.016 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
2015-05-26T16:23:07.373-0200: 64.476: [CMS-concurrent-abortable-preclean-start]
2015-05-26T16:23:08.446-0200: 65.550: [CMS-concurrent-abortable-preclean: 0.167/1.074 secs] [Times: user=0.20 sys=0.00, real=1.07 secs]
2015-05-26T16:23:08.447-0200: 65.550: [GC (CMS Final Remark) [YG occupancy: 387920 K (613440 K)]65.550: [Rescan (parallel) , 0.0085125 secs]65.559: [weak refs processing, 0.0000243 secs]65.559: [class unloading, 0.0013120 secs]65.560: [scrub symbol table, 0.0008345 secs]65.561: [scrub string table, 0.0001759 secs][1 CMS-remark: 10812086K(11901376K)] 11200006K(12514816K), 0.0110730 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
2015-05-26T16:23:08.458-0200: 65.561: [CMS-concurrent-sweep-start]
2015-05-26T16:23:08.485-0200: 65.588: [CMS-concurrent-sweep: 0.027/0.027 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
2015-05-26T16:23:08.485-0200: 65.589: [CMS-concurrent-reset-start]
2015-05-26T16:23:08.497-0200: 65.601: [CMS-concurrent-reset: 0.012/0.012 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

注意:年轻代Minor GC 可以与老年代并发标记清除收集器一同工作

CMS的Full GC包括7个阶段,1-5是标记阶段,会有两次stop-the-world(Initial Mark 和 Final Remark)

Phase 1: Initial Mark
初始标记:会stop-the-world,因为要标记Old Generation当中GC Roots和对年轻代对象的引用对象;GC Root直接引用的对象不多,所以很快。这是CMS期间的两大停摆事件之一。 此阶段的目标是标记Old Generation中的所有对象,这些对象要么是直接的GC ROOT,要么是从年轻代中的某些活动对象引用的。 后者很重要,因为Old Generation是单独收集的。

1:GC触发的时钟时间和相对于JVM启动的时间

2:区分GC所处阶段,CMS Initial Mark表示初始标记,标记所有Old Generation中的GC Roots

3:老年代对象数据占用的空间大小

4:老年代总的空间大小

5:堆已使用的空间大小

6:堆总的空间大小

7:初始标记的持续时间

-user:占用CPU的时间长短

-sys:花费在系统调用或等待系统事件的时间长短

-real:应用挂起的时间长短

2020-12-14T09:13:05.211-0800: 1.425: [GC (CMS Initial Mark) [1 CMS-initial-mark: 4983K(118784K)] 12084K(210944K), 0.0006673 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Phase 2: Concurrent Mark
并发标记:在第一阶段初始标记的基础上,从GC Roots遍历所有Old Generation的对象并且标记所有存活的对象,是并发标记,不会stop-the-world。不是所有在老年代中的存活的对象都会被标记,因为在GC在执行期间会改变引用,被改变对象引用区域叫做Card,对象被标记为dirty。由第一阶段标记过的对象出发,所有可达的对象都在本阶段标记。

2020-12-14T09:13:05.211-0800: 1.426: [CMS-concurrent-mark-start]

2020-12-14T09:13:05.216-0800: 1.430: [CMS-concurrent-mark: 0.004/0.004 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]

1:CMS-concurrent-mark:收集器执行阶段,从GC Roots遍历所有老年代对象并标记存活对象(不是所有的存活对象都会别标记,因为没有stop-the-world,应用任然可以改变对象引用)

2:并发标记占用0.35的CPU时间,0.035s的挂钟时间(从事件从开始运行到结束,时钟走过的时间,这其中包含了进程在阻塞和等待状态的时间 (挂钟时间 = 阻塞时间 + 就绪时间 +运行时间))

3:Times在并发标记中基本上无意义,因为它是从CMS-concurrent-mark-start开始,并且包含有除并发标记以外的时间消耗。

Phase 3: Concurrent Preclean

扩展阅读(https://blog.csdn.net/enemyisgodlike/article/details/106960687)

不会stop-the-world,对card区域的dirty对象进行处理,并将从dirty对象可达的对象进行mark;除此之外还会做必要的对象清除和为Final Remark做准备。在本阶段,会查找前一阶段执行过程中,从新生代晋升或新分配或被更新的对象。通过并发地重新扫描这些对象,预清理阶段可以减少下一个stop-the-world 重新标记阶段的工作量。

2020-12-14T09:13:07.918-0800: 4.132: [CMS-concurrent-preclean-start]

2020-12-14T09:13:07.919-0800: 4.133: [CMS-concurrent-preclean: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

1:标识concurrent-preclean阶段

2:并发预清理占用0.016的CPU时间,0.016s的挂钟时间(从事件从开始运行到结束,时钟走过的时间,这其中包含了进程在阻塞和等待状态的时间 (挂钟时间 = 阻塞时间 + 就绪时间 +运行时间))

3:无意义,因为是从并发标记阶段开始计时的。

Phase 4: Concurrent Abortable Preclean.

-XX:CMSScheduleRemarkEdenSizeThreshold=2097152Bytes(2M):当Eden

不会stop-the-world,尽可能与stop-the-world的Final Remark独立开,因为这个阶段需要重复地做一些事情直到达到某个条件停止,执行时间取决于多种因素(迭代次数、做的有效工作量的数量、挂钟时间等);增加这一阶段是为了让我们可以控制这个阶段的结束时机,比如扫描多长时间(默认5秒)或者Eden区使用占比达到期望比例(默认50%)就结束本阶段。

2020-12-14T09:13:07.919-0800: 4.133: [CMS-concurrent-abortable-preclean-start]

2020-12-14T09:13:08.067-0800: 4.281: [CMS-concurrent-abortable-preclean: 0.148/0.148 secs] [Times: user=0.30 sys=0.02, real=0.15 secs]

1:区分并发标记清除垃圾收集执行阶段,这里是concurrent-abortable-preclean阶段

2:并发可中止的预清理阶段,占用0.167的CPU时间,1.074s的挂钟时间(从事件从开始运行到结束,时钟走过的时间,这其中包含了进程在阻塞和等待状态的时间 (挂钟时间 = 阻塞时间 + 就绪时间 +运行时间))

3:无意义,因为是从并发标记阶段开始计时的。

Phase 5: Final Remark

第二个会stop-the-world的阶段,最后标记在老年代所有存活的对象;为了避免多个stop-the-world的收集器连续执行,CMS尽可能在Young Generation为0k的时候执行Final Remark;

2020-12-14T09:13:05.423-0800: 1.638: [GC (CMS Final Remark) [YG occupancy: 47292 K (92160 K)]2020-12-14T09:13:05.423-0800: 1.638: [Rescan (parallel) , 0.0098615 secs]2020-12-14T09:13:05.433-0800: 1.648: [weak refs processing, 0.0000618 secs]2020-12-14T09:13:05.433-0800: 1.648: [class unloading, 0.0023545 secs]2020-12-14T09:13:05.436-0800: 1.650: [scrub symbol table, 0.0024580 secs]2020-12-14T09:13:05.438-0800: 1.653: [scrub string table, 0.0003786 secs][1 CMS-remark: 4983K(118784K)] 52275K(210944K), 0.0155274 secs] [Times: user=0.10 sys=0.00, real=0.01 secs]

1:GC事件触发时间

2:GC事件类型:CMS Final Remark 这里表示CMS的最终标记过程,会标记在Old Generation所有存活的对象(包括在前几个标记阶段创建或修改的对象引用)

3:YG occupancy:当前年轻代对象数据占用空间大小和总的空间大小

4:Rescan(parallel):当应用挂起时,rescan并行地扫描所有的老年代中存活的对象,这里表明是并行执行并且花费了0.0085125秒

5:weak refs processing:最终标记阶段的子阶段是处理弱引用,花费的时间以及相对于JVM启动时间的时间戳

6:class unloading:卸载未使用的类,带有花费的时间和相对于JVM启动时间的时间戳

7:scrub symbol table:清理符号表以及其花费的时间

-scrub string table:清理字符表(类级别的元数据和内部化字符串)及其花费的时间

8:CMS-remark:老年代存储对象占用空间大小和老年代当前的总共大小

9:这一GC阶段前后堆的对象数据占用空间大小以及堆的总空间大小

10:这一GC阶段的花费的时间

11: -user:cup占用时间   -sys:花费在系统调用或等待系统事件的时间

注意:到此,总共的CMS的五个标记阶段已完成

Phase 6: Concurrent Sweep

不会stop-the-world,这一阶段的主要目的是清除垃圾对象并回收垃圾对象占用的内存空间以备以后使用。

1:CMS-concurrent-sweep:清理未标记的对象并回收内存空间

2:对应的cpu占用时间和这一阶段的挂钟时间

3:无意义,记录的是从CMS标记开始至今的时间,远超过这一阶段花费的时间。

Phase 7: Concurrent Reset

并发重置,重置CMS算法内部的数据结构,为下一CMS周期做准备

2020-12-14T09:13:08.096-0800: 4.310: [CMS-concurrent-reset-start]

2020-12-14T09:13:08.096-0800: 4.310: [CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

1:区分CMS阶段的标志

2:这一阶段占用CPU的时间和挂钟时间

3:无意义,记录的是从CMS标记开始至今的时间,远超过这一阶段花费的时间。

Concurrent Mark and Sweep相关推荐

  1. Background sticky concurrent mark sweep GC freed 842(58KB) AllocSpace objects

    Background sticky concurrent mark sweep GC freed 842(58KB) AllocSpace objects, 5(11MB) LOS objects, ...

  2. JVM系列(十一) 垃圾收集器之 Concurrent Mark Sweep 并发标记清除

    垃圾收集器之 Concurrent Mark Sweep 并发标记清除 上几篇文章我们讲解了单线程垃圾收集器 Serial/SerialOld ,多线程垃圾收集器 Parallel Scavenge/ ...

  3. JVM的CMS(concurrent mark sweep)四个阶段详细介绍

    1.initial mark(初始标记):通过GC roots找到根对象,这个过程会STW(stop the world),由于根对象并不多,所以STW的时间不会长. 2.concurrent mar ...

  4. java 序列化 内存溢出_Gson序列化问题导致的内存溢出,tip:Background sticky concurrent mark sweep GC freed...

    MFC 单文档消息执行顺序. theApp构造, InitInstance void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO* lpMMI) BOOL CMyF ...

  5. 关于Java 垃圾收集器你应该知道这些

    如果Java虚拟机中标记清除算法.标记整理算法.复制算法.分代算法这些属于GC收集算法中的方法论,那么"GC收集器"则是这些方法论的具体实现. 概念准备 下面了解几个概念以帮助后面 ...

  6. Minor GC、Major GC和Full GC之间的区别(转)

    在 Plumbr 从事 GC 暂停检测相关功能的工作时,我被迫用自己的方式,通过大量文章.书籍和演讲来介绍我所做的工作.在整个过程中,经常对 Minor.Major.和 Full GC 事件的使用感到 ...

  7. 使用 Kafka 和 Spark Streaming 构建实时数据处理系统

    使用 Kafka 和 Spark Streaming 构建实时数据处理系统  来源:https://www.ibm.com/developerworks,这篇文章转载自微信里文章,正好解决了我项目中的 ...

  8. Java9中的GC 调优

    垃圾收集器与内存分配策略参考目录: 1.判断Java 对象是否死亡 2.Java 中的四种引用 3.垃圾收集算法 4.内存分配与回收策略 在经过了几次跳票之后,Java 9终于在原计划日期的整整一年之 ...

  9. 30.jvm.gc(GC之详解CMS收集过程和日志分析)

    30.jvm.gc(GC之详解CMS收集过程和日志分析) 30.1.话题引入 30.2.ParNew and CMS 30.3.日志 30.3.1.GC日志初体验 30.3.2.Minor GC 30 ...

最新文章

  1. python能在excel运行吗-使用PyXLL在Excel中执行Python脚本
  2. xml转json和实体类的两种方式
  3. 两张动图,彻底明白TCP的三次握手与四次挥手
  4. Java语言中的-----访问修饰符
  5. [react] 如何提高组件的渲染效率呢?
  6. js获取图片真实尺寸 - 代码篇
  7. mysql5.6数据库执行mysqldump备份,报1862密码过期的处理方法。
  8. 语音识别技术的原理及研究难点
  9. vivado和modelsim联合仿真实现奇分频
  10. Linux下PHP开启Oracle支持(oci8)
  11. 【翻译】Geometric Features-Based Parking Slot Detection
  12. 凯撒密码(凯撒移位)
  13. 零基础 SQL 数据库小白,从入门到精通的学习路线与书单
  14. 墙壁绘画机器人 ||arduino processing
  15. while(true) Thread.Sleep(XX)我通常是用这种写法,有没有更好的写法或者改进
  16. 微信小程序答题页——swiper渲染优化及swiper分页实现
  17. 计算机专业考研面试题大全———持续更新中
  18. PCIe扫盲——热插拔简要介绍
  19. 一个芯片工作的基本条件
  20. c语言如何实现正负交替输出指令,C语言的谜题

热门文章

  1. el-tree自定义节点内容使用svg和文本
  2. 华硕windows10怎么安装c语言,华硕x441sc笔记本u盘安装win10系统教程
  3. Oracle面试笔试题集
  4. jQuery fade方法
  5. windows10下两台电脑连接局域网怎么设置?
  6. 快钱 java demo_快钱聚合支付(一码付)对接demo
  7. CSS *IS* AWESOME 解读
  8. python nltk是什么_Python文本处理nltk基础
  9. Package missing in current channels
  10. 爆笑中的商业哲理:怎么娶比尔·盖次的女儿!