GC 知识点补充——CMS(gc gcms)
lipiwang 2024-11-15 22:04 13 浏览 0 评论
之前已经讲过了不少有关 GC 的内容,今天准备将之前没有细讲的部分进行补充,首先要提到的就是垃圾收集器。
基础的回收方式有三种:清除、压缩、复制,衍生出来的垃圾收集器有:
Serial 收集器
新生代收集器,使用停止复制算法,使用一个线程进行 GC ,串行,其它工作线程暂停。
使用-XX:+UseSerialGC开关来控制使用Serial + Serial Old模式运行进行内存回收(这也是虚拟机在 Client 模式下运行的默认值)。
ParNew 收集器
新生代收集器,使用停止复制算法,Serial 收集器的多线程版,用多个线程进行 GC ,并行,其它工作线程暂停,关注缩短垃圾收集时间。
使用-XX:+UseParNewGC开关来控制使用ParNew + Serial Old收集器组合收集内存;使用-XX:ParallelGCThreads来设置执行内存回收的线程数。
Parallel Scavenge 收集器
新生代收集器,使用停止复制算法,关注 CPU 吞吐量,即运行用户代码的时间/总时间,比如:JVM 运行 100 分钟,其中运行用户代码 99 分钟,垃 圾收集 1 分钟,则吞吐量是 99% ,这种收集器能最高效率的利用 CPU ,适合运行后台运算(其他关注缩短垃圾收集时间的收集器,如 CMS ,等待时间很少,所以适 合用户交互,提高用户体验)。
使用-XX:+UseParallelGC开关控制使用Parallel Scavenge + Serial Old收集器组合回收垃圾(这也是在 Server 模式下的默认值);使用-XX:GCTimeRatio来设置用户执行时间占总时间的比例,默认 99 ,即 1% 的时间用来进行垃圾回收。使用-XX:MaxGCPauseMillis设置 GC 的最大停顿时间(这个参数只对 Parallel Scavenge 有效),用开关参数-XX:+UseAdaptiveSizePolicy可以进行动态控制,如自动调整 Eden / Survivor 比例,老年代对象年龄,新生代大小等,这个参数在 ParNew 下没有。
Serial Old 收集器
老年代收集器,单线程收集器,串行,使用标记-整理算法,使用单线程进行GC,其它工作线程暂停(注意:在老年代中进行标记-整理算法清理,也需要暂停其它线程),在JDK1.5之前,Serial Old 收集器与 ParallelScavenge 搭配使用。
整理的方法是 Sweep (清除)和 Compact (压缩),清除是将废弃的对象干掉,只留幸存的对象,压缩是移动对象,将空间填满保证内存分为2块,一块全是对象,一块空闲),
Parallel Old 收集器
老年代收集器,多线程,并行,多线程机制与 Parallel Scavenge 差不错,使用标记-整理算法,在 Parallel Old 执行时,仍然需要暂停其它工作线程。
Parallel Old 收集器的整理,与 Serial Old 不同,这里的整理是Copy(复制)和Compact(压缩),复制的意思就是将幸存的对象复制到预先准备好的区域,而不是像Sweep(清除)那样清除废弃的对象。
Parallel Old 在多核计算中很有用。 Parallel Old 出现后(JDK 1.6),与 Parallel Scavenge 配合有很好的效果,充分体现 Parallel Scavenge 收集器吞吐量优先的效果。使用-XX:+UseParallelOldGC开关控制使用Parallel Scavenge + Parallel Old组合收集器进行收集。
CMS
全称 Concurrent Mark Sweep,老年代收集器,致力于获取最短回收停顿时间(即缩短垃圾回收的时间),使用标记-清除算法,多线程,优点是并发收集(用户线程可以和 GC 线程同时工作),停顿小。
使用-XX:+UseConcMarkSweepGC进行ParNew + CMS + Serial Old进行内存回收,优先使用ParNew + CMS(原因见后面),当用户线程内存不足时,采用备用方案Serial Old收集。
如何开始
首先来看一下 CMS 是在什么情况下进行 GC:
- 首先 JVM 根据-XX:CMSInitiatingOccupancyFraction、-XX:+UseCMSInitiatingOccupancyOnly来决定什么时间开始垃圾收集。
- 如果设置了-XX:+UseCMSInitiatingOccupancyOnly,那么只有当老年代占用确实达到了-XX:CMSInitiatingOccupancyFraction参数所设定的比例时才会触发 CMS GC。
- 如果没有设置-XX:+UseCMSInitiatingOccupancyOnly,那么系统会根据统计数据自行决定什么时候触发 CMS GC。因此有时会遇到设置了 80% 比例才 CMS GC,但是 50% 时就已经触发了,就是因为这个参数没有设置的原因。
具体执行
CMS GC 的执行过程,具体来说就是:
初始标记(CMS-initial-mark)
该阶段是 stop the world 阶段,因此此阶段标记的对象只是从 root 集最直接可达的对象。
此阶段会打印 1 条日志:CMS-initial-mark:961330K(1572864K),指标记时,老年代的已用空间和总空间
并发标记(CMS-concurrent-mark)
此阶段是和应用线程并发执行的,所谓并发收集器指的就是这个,主要作用是标记可达的对象,此阶段不需要用户线程停顿。
此阶段会打印 2 条日志:CMS-concurrent-mark-start,CMS-concurrent-mark
预清理(CMS-concurrent-preclean)
此阶段主要是进行一些预清理,因为标记和应用线程是并发执行的,因此会有些对象的状态在标记后会改变,此阶段正是解决这个问题。因为之后的 CMS-remark 阶段也会 stop the world,为了使暂停的时间尽可能的小,也需要 preclean 阶段先做一部分工作以节省时间。
此阶段会打印 2 条日志:CMS-concurrent-preclean-start,CMS-concurrent-preclean
可控预清理(CMS-concurrent-abortable-preclean)
此阶段的目的是使 CMS GC 更加可控一些,作用也是执行一些预清理,以减少 CMS-remark 阶段造成应用暂停的时间。
此阶段涉及几个参数:
-XX:CMSMaxAbortablePrecleanTime:当 abortable-preclean 阶段执行达到这个时间时才会结束。 -XX:CMSScheduleRemarkEdenSizeThreshold(默认2m):控制 abortable-preclean 阶段什么时候开始执行,即当年轻代使用达到此值时,才会开始 abortable-preclean 阶段。 -XX:CMSScheduleRemarkEdenPenetratio(默认50%):控制 abortable-preclean 阶段什么时候结束执行。
此阶段会打印 3 条日志:CMS-concurrent-abortable-preclean-start,CMS-concurrent-abortable-preclean,CMS:abort preclean due to time XXX
重新标记(CMS-remark)
此阶段暂停应用线程,停顿时间比并发标记小得多,但比初始标记稍长,因为会对所有对象进行重新扫描并标记。
此阶段会打印以下日志:
- YG occupancy:964861K(2403008K),指执行时年轻代的情况。
- CMS remark:961330K(1572864K),指执行时老年代的情况。
- 此外,还打印出了弱引用处理、类卸载等过程的耗时。
并发清除(CMS-concurrent-sweep)
此阶段进行并发的垃圾清理。
并发重设状态等待下次CMS的触发(CMS-concurrent-reset)
此阶段是为下一次 CMS GC 重置相关数据结构。
总结
CMS 的收集过程,概括一下就是:2 次标记,2 次预清除,1 次重新标记,1 次清除。
在CMS清理过程中,只有初始标记和重新标记需要短暂停顿用户线程,并发标记和并发清除都不需要暂停用户线程,因此效率很高,很适合高交互的场合。
CMS也有缺点,它需要消耗额外的 CPU 和内存资源。在 CPU 和内存资源紧张,会加重系统负担(CMS 默认启动线程数为( CPU数量 + 3 ) / 4 )。
另外,在并发收集过程中,用户线程仍然在运行,仍然产生内存垃圾,所以可能产生“浮动垃圾”(本次无法清理,只能下一次Full GC才清理)。因此在 GC 期间,需要预留足够的内存给用户线程使用。
所以使用 CMS 的收集器并不是老年代满了才触发 Full GC ,而是在使用了一大半(默认 68% ,即 2/3 ,使用-XX:CMSInitiatingOccupancyFraction来设置)的时候就要进行 Full GC。如果用户线程消耗内存不是特别大,可以适当调高-XX:CMSInitiatingOccupancyFraction以降低 GC 次数,提高性能。如果预留的用户线程内存不够,则会触发 Concurrent Mode Failure,此时,将触发备用方案:使用 Serial Old 收集器进行收集,但这样停顿时间就长了,因此-XX:CMSInitiatingOccupancyFraction不宜设的过大。
还有,CMS 采用的是标记-清除算法,会导致内存碎片的产生,可以使用-XX:+UseCMSCompactAtFullCollection来设置是否在 Full GC 之后进行碎片整理,用-XX:CMSFullGCsBeforeCompaction来设置在执行多少次不压缩的 Full GC 之后,来一次带压缩的 Full GC。
并发和并行
并发收集:
指用户线程与GC线程同时执行(不一定是并行,可能交替,但总体上是在同时执行的),不需要停顿用户线程(其实在 CMS 中用户线程还是需要停顿的,只是非常短,GC 线程在另一个 CPU 上执行);
并行收集:
指多个 GC 线程并行工作,但此时用户线程是暂停的;
所以,Serial 是串行的,Parallel 收集器是并行的,而 CMS 收集器是并发的。
总结
今天了解了一下普通的垃圾收集器,并且详细介绍了 CMS,其特性其实是基于普通的垃圾算法,增加了预处理、预清除的过程,因此效率更加优越。当然它也有自己的缺点,更加消耗资源,因此在选用的时候需要结合实际场景。
有兴趣的话可以访问我的博客或者关注我的公众号、头条号,说不定会有意外的惊喜。
https://death00.github.io/
相关推荐
- 前端入门——css 网格轨道详细介绍
-
上篇前端入门——cssGrid网格基础知识整体大概介绍了cssgrid的基本概念及使用方法,本文将介绍创建网格容器时会发生什么?以及在网格容器上使用行、列属性如何定位元素。在本文中,将介绍:...
- Islands Architecture(孤岛架构)在携程新版首页的实践
-
一、项目背景2022,携程PC版首页终于迎来了首次改版,完成了用户体验与技术栈的全面升级。作为与用户连接的重要入口,旧版PC首页已经陪伴携程走过了22年,承担着重要使命的同时,也遇到了很多问题:维护/...
- HTML中script标签中的那些属性
-
HTML中的<script>标签详解在HTML中,<script>标签用于包含或引用JavaScript代码,是前端开发中不可或缺的一部分。通过合理使用<scrip...
- CSS 中各种居中你真的玩明白了么
-
页面布局中最常见的需求就是元素或者文字居中了,但是根据场景的不同,居中也有简单到复杂各种不同的实现方式,本篇就带大家一起了解下,各种场景下,该如何使用CSS实现居中前言页面布局中最常见的需求就是元...
- CSS样式更改——列表、表格和轮廓
-
上篇文章主要介绍了CSS样式更改篇中的字体设置Font&边框Border设置,这篇文章分享列表、表格和轮廓,一起来看看吧。1.列表List1).列表的类型<ulstyle='list-...
- 一文吃透 CSS Flex 布局
-
原文链接:一文吃透CSSFlex布局教学游戏这里有两个小游戏,可用来练习flex布局。塔防游戏送小青蛙回家Flexbox概述Flexbox布局也叫Flex布局,弹性盒子布局。它决定了...
- css实现多行文本的展开收起
-
背景在我们写需求时可能会遇到类似于这样的多行文本展开与收起的场景:那么,如何通过纯css实现这样的效果呢?实现的难点(1)位于多行文本右下角的展开收起按钮。(2)展开和收起两种状态的切换。(3)文本...
- css 垂直居中的几种实现方式
-
前言设计是带有主观色彩的,同样网页设计中的css一样让人摸不头脑。网上列举的实现方式一大把,或许在这里你都看到过,但既然来到这里我希望这篇能让你看有所收获,毕竟这也是前端面试的基础。实现方式备注:...
- WordPress固定链接设置
-
WordPress设置里的最后一项就是固定链接设置,固定链接设置是决定WordPress文章及静态页面URL的重要步骤,从站点的SEO角度来讲也是。固定链接设置决定网站URL,当页面数少的时候,可以一...
- 面试发愁!吃透 20 道 CSS 核心题,大厂 Offer 轻松拿
-
前端小伙伴们,是不是一想到面试里的CSS布局题就发愁?写代码时布局总是对不齐,面试官追问兼容性就卡壳,想跳槽却总被“多列等高”“响应式布局”这些问题难住——别担心!从今天起,咱们每天拆解一...
- 3种CSS清除浮动的方法
-
今天这篇文章给大家介绍3种CSS清除浮动的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。首先,这里就不讲为什么我们要清楚浮动,反正不清除浮动事多多。下面我就讲3种常用清除浮动的...
- 2025 年 CSS 终于要支持强大的自定义函数了?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1.什么是CSS自定义属性CSS自...
- css3属性(transform)的一个css3动画小应用
-
闲言碎语不多讲,咱们说说css3的transform属性:先上效果:效果说明:当鼠标移到a标签的时候,从右上角滑出二维码。实现方法:HTML代码如下:需要说明的一点是,a链接的跳转需要用javasc...
- CSS基础知识(七)CSS背景
-
一、CSS背景属性1.背景颜色(background-color)属性值:transparent(透明的)或color(颜色)2.背景图片(background-image)属性值:none(没有)...
- CSS 水平居中方式二
-
<divid="parent"><!--定义子级元素--><divid="child">居中布局</div>...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)