cms垃圾收集器采用的回收算法_垃圾回收处理厂

cms垃圾收集器采用的回收算法_垃圾回收处理厂CMSconcurrentmarkssweep并行标记清除垃圾回收机制。此篇文章是根据众多网上资料总结的关于CMS垃圾回收器的相关知识点。便于个人总结和回忆。垃圾回收器类型1、串行回收,Serial回收器,单线程回收,全程stw;2、并行回收,名称以Parallel开头的回收器,多线程回收,全程stw;3、并发回收,cms与G1,多线程分阶段回收,只有某阶段会stw;CMS垃圾回…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

CMS concurrent marks sweep 并行标记清除垃圾回收机制。此篇文章是根据众多网上资料总结的关于CMS垃圾回收器的相关知识点。便于个人总结和回忆。

垃圾回收器类型

1、串行回收,Serial回收器,单线程回收,全程stw;
2、并行回收,名称以Parallel开头的回收器,多线程回收,全程stw;
3、并发回收,cms与G1,多线程分阶段回收,只有某阶段会stw;

CMS垃圾回收器特点

1、cms只会回收老年代和永久代(1.8开始为元数据区,需要设置CMSClassUnloadingEnabled),不会收集年轻代;
2、cms是一种预处理垃圾回收器,它不能等到old内存用尽时回收,需要在内存用尽前,完成回收操作,否则会导致并发回收失败;所以cms垃圾回收器开始执行回收操作,有一个触发阈值,默认是老年代或永久带达到92%;

CMS垃圾回收的七大步骤

找到两张图来帮助理解这几个步骤:
图1:
在这里插入图片描述
图2:
在这里插入图片描述

以下过程参考博客:https://www.jianshu.com/p/2a1b2f17d3e4
1、初始标记:会发生stw
单线程执行
a/标记GC ROOT可达的老年代对象
b/遍历新生代对象,标记可达的老年代对象;
该阶段执行完以后,如图1,灰色标记对象。
2、并发标记
和应用程序并发执行
a/ 1阶段完成后,需要继续递归遍历,标记这些对象的可达对象。
因为该阶段并发执行的,在运行期间可能发生新生代的对象晋升到老年代、或者是直接在老年代分配对象、或者更新老年代对象的引用关
系等等,对于这些对象,都是需要进行重新标记的,否则有些对象就会被遗漏,发生漏标的情况。如图2
为了提高重新标记的效率,该阶段会把上述对象所在的Card标识为Dirty,后续只需扫描这些Dirty Card的对象,避免扫描整个老年代。

3、预清理
a/处理新生代新发现的引用,比如在并发阶段,在Eden区中分配了一个A对象,A对象引用了一个老年代对象B(这个B之前没有被标
记),在这个阶段就会标记对象B为活跃对象。
b/在并发标记阶段,如果老年代中有对象内部引用发生变化,会把所在的Card标记为Dirty(其实这里并非使用CardTable,而是一个
类似的数据结构,叫ModUnionTalble),通过扫描这些Table,重新标记那些在并发标记阶段引用被更新的对象(晋升到老年代的对象/
原本就在老年代的对象)

4、可被终止的预清理

a/处理 From 和 To 区的对象,标记可达的老年代对象
b/和上一个阶段一样,扫描处理Dirty Card中的对象

该阶段发生的前提是,新生代Eden区的内存使用量大于参数CMSScheduleRemarkEdenSizeThreshold 默认是2M,如果新生代的对象
太少,就没有必要执行该阶段,直接执行重新标记阶段。

为什么需要这个阶段,存在的价值是什么?

	因为CMS GC的终极目标是降低垃圾回收时的暂停时间,所以在该阶段要尽最大的努力去处理那些在并发阶段被应用线程更新的老年代对象,这样在暂停的
	重新标记阶段就可以少处理一些,暂停时间也会相应的降低。

当然了,这个逻辑不会一直循环下去,打断这个循环的条件有三个:

	1/可以设置最多循环的次数 CMSMaxAbortablePrecleanLoops,默认是0,意思没有循环次数的限制。
	2/如果执行这个逻辑的时间达到了阈值CMSMaxAbortablePrecleanTime,默认是5s,会退出循环。
	3/如果新生代Eden区的内存使用率达到了阈值CMSScheduleRemarkEdenPenetration,默认50%,会退出循环。(这个条件能够成立的前提是,
	在进行Precleaning时,Eden区的使用率小于十分之一)

如果在循环退出之前,发生了一次YGC,对于后面的Remark阶段来说,大大减轻了扫描年轻代的负担,但是发生YGC并非人为控制,所以只能祈祷这5s内可以来一次YGC。

5、重新标记,会发生stw

在之前的过程中还会存在一些未标记的对象主要包括:

	1、老年代的新对象被GC Roots引用
	2、老年代的未标记对象被新生代对象引用
	3、老年代已标记的对象增加新引用指向老年代其它对象
	4、新生代对象指向老年代引用被删除
也许还有其它情况..

上述对象中可能有一些已经在Precleaning阶段和AbortablePreclean阶段被处理过,但总存在没来得及处理的,所以还有进行如下的处理:

1、遍历新生代对象,重新标记
2、根据GC Roots,重新标记
3、遍历老年代的Dirty Card,重新标记,这里的Dirty Card大部分已经在clean阶段处理过

这个阶段暂停所有用户线程,重新扫描堆中的对象,
进行可达性分析,标记活着的对象。
有了前面的基础,这个阶段的工作量被大大减轻,停顿时间因此也会减少。

注意这个阶段是多线程的。

6、并发清除

7、并发重置
为下个阶段的垃圾回收做准备。

其他关于jvm的博客:
GC和FULLGC发生时间:https://blog.csdn.net/jialiuyang521/article/details/87982459

STW:
https://www.jianshu.com/p/d686e108d15f

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/182600.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号