文章目录

  • Pre
  • 概述
  • 阶段
    • 初始标记 (STW)
    • 并发标记 (用户线程和GC线程并行工作)
    • 重新标记 (STW)
    • 并发清理(用户线程和GC线程并行工作)
    • 并发重置
  • concurrent mode failure 是怎么回事儿
  • CMS核心参数
  • CMS的优缺点
  • ParNew + CMS设置Demo
  • GC算法底层实现
    • 三色标记

Pre

JVM-04垃圾收集Garbage Collection(上)【垃圾对象的判定】

JVM-05垃圾收集Garbage Collection(中)【垃圾收集算法】

JVM-06垃圾收集Garbage Collection(下)【垃圾收集器】

JVM - 再聊GC垃圾收集算法及垃圾收集器


概述

Concurrent Mark Sweep 并发标记清除 。

CMS 收集器是一种以获取最短回收停顿时间为目标的收集器。

它非常符合在注重用户体验的应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作 。

从名字( Mark Sweep )上也可以看出 CMS收集器是一种 “标记-清除”算法实现的垃圾收集器。


阶段

初始标记 (STW)

初始标记阶段,会Stop the word , 这个阶段CMS仅标记被GC Root直接引用的对象,所以速度很快。

为什么这个阶段要STW呢?

试想一下,如果初始标记阶段 GC线程和用户线程同时运行,GC的过程中,用户线程还是会有新的垃圾对象产生 ,那啥时候能标记完,徒增复杂。 同时CMS设计的理念就是用户感知至上,所以虽然STW,但也尽量缩短STW的时间,所以选择了仅标记被GC Root直接引用的对象,而无需遍历整个堆 。


并发标记 (用户线程和GC线程并行工作)

经过了上一步的初始标记, 已经将GC Root 直接引用的对象标记完成。

CMS 老年代的Garbage Collector , 回收的是整个堆的垃圾对象,效率随着堆的大小成反比 ( 如果堆比较大,比如10G,CMS也是有点吃力的,所以才有了G1)

为了避免GC时间过长,这个阶段CMS 让用户线程和 GC线程同时工作,尽量减少用户线程的停顿。 GC线程这个时候就要从GC Roots的直接关联对象开始遍历整个对象图,这个耗时最长。 所以CMS重点优化了这块 。 I

用户线程和GC线程并行工作,多少都会存在一些问题 。因为用户程序继续运行,可能会有导致已经标记过的对象状态发生改变。

试想一下 GC工作的时候,用户线程也在工作

  1. 如果GC完成后,当时遍历的用户线程引用的对象由不是垃圾对象,变成了垃圾对象 ,那是不是就 漏标了?
  2. 如果GC线程运行中,当时标记的对象是垃圾对象,但是用户线程运行的过程中又把这个对象重新引用了,那是不是 错标了 ?

怎么办呢? CMS设计了 下个阶段 重新标记 来修复这个阶段因对象状态变更导致的标记错误。


重新标记 (STW)

这个阶段主要是修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。 所以这个时候要STW,不然还是会出现阶段二的情况。

这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短

如何重新标记呢? 这里只要采用 三色标记中的增量更新算法


并发清理(用户线程和GC线程并行工作)

又是并行执行

如果这个清理阶段又有新的对象进来(肯定没有被标记,因为上一步已经标记过了),这个时候怎么办? 也删掉? 还不是垃圾对象啊 删掉那肯定不行。该怎么办呢?

CMS是这样处理的: 对于新增对象会被标记为黑色不做任何处理

这样的对象被称为 【浮动垃圾】, 标记黑色,本次不处理,等下次GC。


并发重置

经过这么一轮的标记,最后的阶段 肯定是把 标记清除掉,等待下一轮 ~


concurrent mode failure 是怎么回事儿

本身full GC 就是因为老年代没有空间了, 在 并发标记 和 并发清除阶段 是 用户线程和GC线程 并行执行, 如果这个时候 用户线程又产生了一些大对象或者符合条件的对象晋升到了老年代, 这个时候 老年代没有空间存放这些对象了,GC一边回收,系统一边运行,也许没回收完就再次触发full gc , 就出现了 “concurrent mode failure” .

出现这个情况,CMS是怎么处理呢? 直接OOM?

显然不是,CMS会Stop the word , 然后使用Serial Old 单线程 来进行垃圾回收。 尽量避免这种情况,效率非常低。

如何避免呢? 可以合理设置CMS的参数 (-XX:CMSInitiatingOccupancyFraction) 默认92% ,可以将这个值设置为80%(根据业务考量该值,你的系统大对象多的话 ,当然了,你设置了 80% 就意味着你老年代将会有20%的空间不可用,这部分空间仅能用来存放GC过程中新的对象,需要合理评估),尽量避免并发失败的情况的发生。


CMS核心参数

  • -XX:+UseConcMarkSweepGC:启用cms
  • -XX:ConcGCThreads:并发的GC线程数
  • -XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理,其目的是为了减少内存碎片
  • -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一次
  • -XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认是92%)
  • -XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整
  • -XX:+CMSScavengeBeforeRemark:在CMS GC前启动一次minor gc,目的在于减少老年代对年轻代的引用,降低CMS GC的标记阶段时的开销,一般CMS的GC耗时 80%都在标记阶段
  • -XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW的时间
  • -XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW的时间

CMS的优缺点

优点

  1. 并发收集
  2. 低停顿 ,用户体验至上

缺点:

  1. 用户线程和GC线程有可能争抢CPU资源
  2. 无法处理浮动垃圾 , 在并发标记和并发清理阶段又产生垃圾,这种浮动垃圾只能等到下一次gc再清理了
  3. 回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生, 可以通过参数-XX:+UseCMSCompactAtFullCollection让jvm在执行完标记清除后再做整理,从而实现“标记-整理”的效果,减少内存碎片。 还有个参数 -XX:CMSFullGCsBeforeCompaction 代表多少次Full GC以后整理一下内存碎片,默认为0 即每次Full GC之后都会整理内存碎片。
  4. 执行过程中的不确定性,会存在上一次垃圾回收还没执行完,然后垃圾回收又被触发的情况 。 比如在并发标记和并发清理阶段会出现concurrent mode failure,这个时候会STW,会切换到Serial Old ,效率非常低。

ParNew + CMS设置Demo

-Xms3072M -Xmx3072M -Xmn2048M -Xss1M  -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M  -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5 -XX:PretenureSizeThreshold=1M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=92 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=3

没有标准答案,需要依据自己的业务特点,进行合理的参数调优。


GC算法底层实现

三色标记

在并发标记的过程中,应用线程也在运行,所以GC线程在运行期间应用线程使用的对象之间的引用可能发生变化,会存在多标和漏标的现象。

JVM把Gcroots可达性分析遍历对象过程中遇到的对象, 按照“是否访问过”这个条件标记成以下三种颜色 : 黑 灰 白

  • 黑色: 表示对象已经被垃圾收集器访问过, 且这个对象的所有引用都已经扫描过。 黑色的对象代表已经扫描过, 它是安全存活的, 如果有其他对象引用指向了黑色对象, 无须重新扫描一遍。 黑色对象不可能直接(不经过灰色对象) 指向某个白色对象。

  • 灰色: 表示对象已经被垃圾收集器访问过, 但这个对象上至少存在一个引用还没有被扫描过。

  • 白色: 表示对象尚未被垃圾收集器访问过。 显然在可达性分析刚刚开始的阶段, 所有的对象都是白色的, 若在分析结束的阶段, 仍然是白色的对象, 即代表不可达。

JVM - CMS深度剖析相关推荐

  1. JAVA深度剖析之JVM的体系结构

    JAVA深度剖析之JVM的体系结构 JAVA深度剖析之JVM的体系结构: JVM的生命周期 JVM实例的诞生:当启动一个Java程序时,一个JVM实例就产生了,任何一个拥有publicstaticvo ...

  2. G1垃圾收集器深度剖析

    G1垃圾收集器深度剖析 一.G1垃圾收集器概述 1.1 思考 开始学习前,抛出两个常见面试问题:1.G1的回收原理是什么?为什么G1比传统的GC回收性能好?2.为什么G1如此完美仍然会有ZGC?简单的 ...

  3. c语言深度剖析第三版pdf_入门到入坟,蕴含全网最强知识点3283页笔记、pdf教程,活到老,学到老...

    又到了"金九银十"面试求职高峰期,在金三银四时也参与过不少面试,2020都说工作不好找,也是对开发人员的要求变高.前段时间自己有整理了一些Java后端开发面试常问的高频考点问题做成 ...

  4. 深度剖析Java数据结构之迭代器(Iterator)

    一.什么是迭代器 我们知道,JVM是用C/C++编写的.在百度百科中,迭代器是解释是迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定 ...

  5. 《AngularJS深度剖析与最佳实践》一1.4 实现第一个页面:注册

    本节书摘来自华章出版社<AngularJS深度剖析与最佳实践>一书中的第1章,第1.4节,作者 雪狼 破狼 彭洪伟,更多章节内容可以访问云栖社区"华章计算机"公众号查看 ...

  6. libevent源码深度剖析

    原文地址:http://blog.csdn.net/sparkliang/article/details/4957667 libevent源码深度剖析一 --序幕 张亮 1 前言 Libevent是一 ...

  7. libevent源码深度剖析十一

    libevent源码深度剖析十一 --时间管理 张亮 为了支持定时器,Libevent必须和系统时间打交道,这一部分的内容也比较简单,主要涉及到时间的加减辅助函数.时间缓存.时间校正和定时器堆的时间值 ...

  8. 《AngularJS深度剖析与最佳实践》一第1章 从实战开始

    本节书摘来自华章出版社<AngularJS深度剖析与最佳实践>一书中的第1章,作者 雪狼 破狼 彭洪伟,更多章节内容可以访问云栖社区"华章计算机"公众号查看 第1章 从 ...

  9. 深度剖析:Redis分布式锁到底安全吗?看完这篇文章彻底懂了!

    ‍‍‍‍‍‍‍‍‍‍‍‍阅读本文大约需要 20 分钟. 大家好,我是 Kaito. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题,很多文章已经写烂了 ...

最新文章

  1. 大学计算机数学基础2,大学计算机基础(第2版)
  2. 暴涨!BTC忠实粉丝转向BCH为BCH网络添砖加瓦
  3. 没解决这个7次方程问题,为何这三个数学家却很开心
  4. python创建一个新的txt文件-如何在python中编辑文本文件并创建一个新的文本文件?...
  5. C#-通过OpcUA监控设备
  6. 快速融入新团队的一点个人体会
  7. 二 Java开发环境搭建
  8. NVIDIA助力SiemensPLMSoftware“工业4.0创新实验室”,携手推进中国制造创新之路
  9. 梦想还是要有的,万一实现了呢
  10. 前端技术之_CSS详解第三天
  11. 如何做一个“擅长” Google 搜索的开发专家?
  12. 【开发经验】在Flutter中使用dart的单例模式
  13. 用条件运算符编写程序判断一个人的体重是否为标准体重
  14. 170319 剑指offer 1.把一个字符串转化成整数(简单问题的全面性考虑)
  15. 单元货格式自动化立体仓库AR/RS货架 高效的货位管理及空间利用率的使用
  16. linux下添加三菱触摸屏usb驱动,[转载]三菱触摸屏GT Works3和PLC GX Works2编程软件下载...
  17. Android版微信跳一跳小游戏如何利用技术手段达到高分!
  18. 网络爬虫异常处理总结
  19. 力扣刷题 DAY_62 回溯
  20. HTML5视频自动循环播放

热门文章

  1. Pull和SAX解析XML,以解析中国省市列表为例子
  2. js跳转传递php参数,将JS / Jquery中的参数传递到另一页上的PHP
  3. 稳定匹配算法python实现
  4. MoCo论文中的Algorithm 1伪代码解读
  5. pip 另一种安装方法:python setup.py install
  6. NTU课程:MAS714 (3)Graph Algorithms
  7. 文巾解题 695. 岛屿的最大面积
  8. MATLAB实战系列(九)-遗传算法(GA)求解旅行商问题(TSP)思路解析
  9. vue ui 报错errno:-4058解决办法
  10. 机器学习入门书籍导读-工程高等代数