当前位置:网站首页>CMS垃圾收集器
CMS垃圾收集器
2020-11-08 20:13:00 【入门小站】
CMS垃圾收集器收集详细步骤
- 初始标记(Stop the world)
- 并发标记
- 预清理
- 可被终止的预清理
- 重新标记(Stop the world)
- 并发清除
- 并发重置
初始标记
> 标记GcRoots直接可达老年对象,新生代存活对象引用的老年代对象.整个过程在JDK1.7中是单线程的在JDK1.8中是多线程的(通过CMSParallelInitialMarkEnabled参数调整)。这个过程会导致STW。
并发标记
> 从初始标记
阶段标记过的对象开始,标记其它存活对象,这个阶段垃圾回收线程和应用线程同时运行。由于是同时运行,应用线程还在跑,会导致对象的晋升,对象引用的变化,特殊对象直接分配到老年代。这些受到影响的老年代对象所在的Card会被标记成Dirty,用于重新标记阶段扫描,老年代对象的Card被标记为Dirty的可能原因如下面绿线所示。
预清理
> 由于上一个阶段是并发执行的未标记的变化对象只是标记成了Dirty对象,还没有处理,预清理
就是来标记这些Dirty对象
。如下图:在并发标记阶段3号Card被标志为Dirty。这个阶段是为重新标记
阶段做准备。
预清理将6号标志为存活对象
可被终止的预清理
> 这个阶段也是为重新标志阶段做准备,在进入重新标志阶段前,最好能进行一个Minor GC,将年轻代清理一遍, 这样可以清除大部分年轻代的对象(绝大部分年轻代对象朝生夕死),尽量缩短重新标记
阶段停顿时间,CMS还提供了CMSScavengeBeforeRemark参数,可以在进入重新标记之前强制进行依次Minor gc。
重新标志(remark)
> 预清理
和可被终止的预清理
都是为重新标志
阶段做准备,由于重新标志
阶段会发生(STW),所以要保证尽肯能的停顿时间段,不然就会影响应用程序的用户体验。这个阶段扫描的目标是:年轻代+GC Roots+Dirty老年代对象,这个阶段是多线程的(XX:+CMSParallelRemarkEnabled)。
并发清除
> 用户线程被激活,那些未被标志的对象会被清除。'
并发重置
> CMS垃圾收集器参数回到初始状态,为下一次垃圾收集做准备。
使用CMS垃圾收集器要注意的问题
重新标记
停顿时间过长
> 80%的时间花在重新标志
阶段,如果发现重新标志
阶段停顿时间过长,可尝试添加-XX:+CMSScavengeBeforeRemark
,在重新标志
之前做一次Minor GC
,目的是减少对老年代对象的无效引用,降低重新标志
的开销。
内存碎片问题
> CMS是基于标记-清除算法的,CMS只会删除垃圾对象,不会对内存空间做压缩,会造成内存碎片。我们需要用 -XX:CMSFullGCsBeforeCompaction=n
参数来调整,含义是在上一次CMS并发执行过后,还要执行多少次Full GC
才做内存压缩.
concurrent mode failure
> 在CMS GC过程中由于应用程序也在跑,当年轻代满了,执行了Minor GC
这时候,需要将存活对象放入老年代,而此时老年代空间也不足,这时CMS还没有机会回收老年代。可以设置以下两个参数
- -XX:CMSInitiatingOccupancyFraction=75
> CMS对内存的占用率达到75%将启动GC,默认为92%,太高将导致promotion failed
- -XX:+UseCMSInitiatingOccupancyOnly
> 如果没有设置UseCMSInitiatingOccupancyOnly
,只设置了CMSInitiatingOccupancyFraction
那么JVM只在第一次使用,后续会进行自动调整。
> 为什么要设置以上两个参数,在垃圾收集阶段,用户线程还在运行,所以必须要留够空间让用户线程运行。CMS前五个阶段都是标记存活对象的,除了”初始标记”和”重新标记”阶段会stop the word ,其它三个阶段都是与用户线程一起跑的,就会出现这样的情况gc线程正在标记存活对象,用户线程同时向老年代提升新的对象,清理工作还没有开始,old gen已经没有空间容纳更多对象了,这时候就会导致concurrent mode failure, 然后就会使用串行收集器回收老年代的垃圾,导致停顿的时间非常长。 CMSInitiatingOccupancyFraction参数要设置一个合理的值,设置大了,会增加concurrent mode failure发生的频率,设置的小了,又会增加CMS频率,所以要根据应用的运行情况来选取一个合理的值。如果发现这两个参数设置大了会导致full gc,设置小了会导致频繁的CMS GC,说明你的老年代空间过小,应该增加老年代空间的大小了。
promotion failed
> 在进行Minor GC时,Survivor space放不下,对象只能放入老年代,而此时老年代也放不下,大多数情况是老年代内存碎片太多,导致没有连续的空间存放对象。
过早的晋升和晋升失败
> 发生Minor GC时,如果对象过大(Survivor Space存放不下)基本上会放到老年代,这种现象被称为对象过早晋升,这将导致老年代被中短期对象增张,肯能导致严重的性能问题。如果老年代也满了,会触发Full GC,这将会导致遍历整个堆,晋升失败。
解决方案
- 如果是因为内存碎片导致的大对象提升失败,cms需要进行空间整理压缩;
- 如果是因为提升过快导致的,说明Survivor 空闲空间不足,那么可以尝试调大 Survivor;
- 如果是因为老年代空间不够导致的,尝试将CMS触发的阈值调低。
CMS总结
- CMS只收集老年代,响应速度优先。
- 重新标记会STW,停顿时间较长,所以在这之前进行一次Minor GC,会减少很多对老年代对象的无效引用。
- 内存碎片问题导致的Full GC,请使用
-XX:CMSFullGCsBeforeCompaction=n
,有规律对内存进行整理减少内存碎片。 - JDK1.7,JDK1.8设置CMS垃圾收集器
XX:+UseConcMarkSweepGC
几个重要的CMS参数
-XX:CMSFullGCsBeforeCompaction=n
Full GC
n 次后进行内存压缩整理-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSInitiatingOccupancyOnly
内存占用70%将触发CMS GC
-XX:+CMSScavengeBeforeRemark
CMS GC前执行一次Minor GC
版权声明
本文为[入门小站]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4232146/blog/4708332
边栏推荐
- [cloud service] there are so many ECS instances on alicloud server, how to select the type? Best practice note
- C/C++知识分享: 函数指针与指针函数,看完这篇你还能不懂?
- Django之简易用户系统(3)
- EntityFramework Core上下文实例池原理分析
- C / C + + knowledge sharing: function pointer and pointer function, can you understand after reading this article?
- Express框架
- Not a programmer, code can't be too ugly! The official writing standard of Python: pep8 everyone should know
- latex入门
- iptables从入门到掌握
- 都说程序员钱多空少,程序员真的忙到没时间回信息了吗?
猜你喜欢
Simple process of reading pictures by QT program developed by Python
Use markdown
Brief VIM training strategy
Flink's sink: a preliminary study
使用Fastai开发和部署图像分类器应用
第一部分——第1章概述
If the programming language as martial arts unique! C++ is Jiu Yin Jing. What about programmers?
Flink系列(0)——准备篇(流处理基础)
Swagger介绍和应用
One minute comprehensive understanding of forsage smart contract global shared Ethereum matrix plan
随机推荐
CountDownLatch 瞬间炸裂!同基于 AQS,凭什么 CyclicBarrier 可以这么秀?
Solve the failure of go get download package
Liteos message queuing actual combat
Function classification big PK! How to use sigmoid and softmax respectively?
Summary: in October, more investment management strategies have come to the new overseas defi project!
Why need to use API management platform
An online accident caused by improper use of thread pool
Dynamic relu: Microsoft's refreshing device may be the best relu improvement | ECCV 2020
Flink系列(0)——准备篇(流处理基础)
Regular backup of WordPress website program and database to qiniu cloud
Dynamic programming: maximum subarray
Looking for a small immutable dictionary with better performance
Summary of interface test case ideas
数组初相识
总结: 10月海外DeFi新项目,更多资管策略来了!
Express框架
精通高并发与多线程,却不会用ThreadLocal?
Talk about go code coverage technology and best practices
解决go get下载包失败问题
AI perfume is coming. Will you buy it?