[[HotSpot 虚拟机垃圾收集调优指南-JavaSE11-笔记]-7-并发标记扫描 (CMS) 收集器

7-并发标记扫描 (CMS) 收集器

Concurrent Mark Sweep (CMS) 收集器是为喜欢更短的垃圾收集暂停并且能够在应用程序运行时与垃圾收集器共享处理器资源的应用程序而设计的。

通常,具有相对较大的长期数据集(大型老一代)并在具有两个或更多处理器的机器上运行的应用程序往往会从使用此收集器中受益。CMS 收集器通过命令行选项启用-XX:+UseConcMarkSweepGC

JDK11中,CMS 收集器已弃用。强烈考虑改用G1垃圾优先收集器

7.1 并发标记扫描收集器的性能和结构

与其他可用的收集器类似,CMS 收集器是分代的;因此,Minor GC和Full GC都会发生。CMS 收集器尝试通过使用单独的垃圾收集器线程执行应用程序线程同时跟踪可达对象,从而减少由于Full GC收集而导致的暂停时间

在每个Full GC收集周期中,CMS 收集器在收集开始时暂停所有应用程序线程一小段时间,然后再次向收集中间暂停。第二个停顿往往是两个停顿中较长的一个。多个线程在两个暂停期间执行收集工作。一个或多个垃圾收集器线程完成收集的其余部分(包括大部分活动对象的跟踪和无法访问的对象的清除)。Minor GC可以与正在进行的主要循环交错,并且以类似于并行收集器的方式完成(特别是,应用程序线程在Minor GC收集期间停止)。

7.2 并发模式失败

CMS 收集器使用一个或多个与应用程序线程同时运行的垃圾收集器线程,目的是在老年代变满之前完成对它的收集

如前所述,在正常操作中,CMS 收集器在应用程序线程仍在运行的情况下完成大部分跟踪和清扫工作,因此应用程序线程只会看到短暂的暂停。但是,如果 CMS 收集器无法在老年代填满之前完成对不可达对象的回收,或者如果老年代中的可用空闲空间块无法满足分配,则应用程序将暂停并完成收集所有应用程序线程都停止了。无法同时完成收集称为并发模式故障,表示需要调整 CMS 收集器参数。如果并发收集被显式垃圾收集(System.gc()) 或者对于需要为诊断工具提供信息的垃圾收集,则报告并发模式中断。

7.3 GC 时间过长和 OutOfMemoryError

如果在垃圾收集上花费的时间过多CMS 收集器会抛出一个OutOfMemoryError:如果超过 98% 的总时间花在垃圾收集上,而只有不到 2% 的堆被回收,那么内存不足错误被抛出。

此功能旨在防止应用程序长时间运行,同时由于堆太小而几乎没有进展或没有进展。-XX:-UseGCOverheadLimit 如有必要,可以通过将选项添加到命令行 来禁用此功能。

该策略与并行收集器中的策略相同,只是执行并发收集所花费的时间不计入 98% 的时间限制。换句话说,只有在应用程序停止时执行的收集才会计入过多的 GC 时间。此类收集通常是由于并发模式故障或显式收集请求(例如,对 的调用System.gc())。

7.4 并发标记扫描收集器和浮动垃圾

CMS 收集器与 Java HotSpot VM 中的所有其他收集器一样,是一个跟踪收集器,它至少标识堆中所有可访问的对象。

Richard Jones 和 Rafael D. Lins 在他们的出版物Garbage Collection: Algorithms for Automated Dynamic Memory中,它是一个增量更新收集器。因为应用程序线程和垃圾收集器线程在主要收集期间同时运行,所以由垃圾收集器线程跟踪的对象可能随后在收集过程结束时变得不可访问。这种尚未被回收的不可达对象被称为 浮动垃圾. 浮动垃圾的数量取决于并发收集周期的持续时间和引用更新的频率,也称为mutations,由应用程序。此外,由于年轻代和老年代是独立收集的,因此每个都充当另一个根的来源。作为粗略的指导,尝试将老年代的大小增加 20% 以解决浮动垃圾的问题。在一个并发收集周期结束时堆中的浮动垃圾在下一个收集周期中被收集

7.5 并发标记扫描收集器暂停

CMS 收集器在并发收集周期中暂停应用程序两次

第一个暂停是将可从根(例如,来自应用程序线程堆栈和寄存器、静态对象等的对象引用)和堆中的其他地方(例如,年轻代)直接访问的对象标记为活动的。这第一次暂停被称为initial mark pause.

第二个暂停出现在并发跟踪阶段的末尾,并在 CMS 收集器完成跟踪该对象后查找由于应用程序线程更新对象中的引用而被并发跟踪遗漏的对象。这第二次暂停被称为remark pause.

7.6 并发标记扫描收集器并发阶段

可达对象图的并发跟踪发生在初始标记暂停和重新标记暂停之间。

在此并发跟踪阶段,一个或多个并发垃圾收集器线程可能正在使用原本可用于应用程序的处理器资源。因此,即使应用程序线程没有暂停,受计算限制的应用程序可能会在此阶段和其他并发阶段看到应用程序吞吐量相应下降。重新标记暂停后,并发清扫阶段收集标识为无法访问的对象。一个收集周期完成后,CMS 收集器等待,几乎不消耗任何计算资源,直到下一个主要收集周期开始。

7.7 启动并发收集周期

使用串行收集器,只要老年代变满并且所有应用程序线程在收集完成时停止就会发生Full GC。相反,CMS 收集器中并发收集的开始必须定时,以便收集可以在老年代满之前完成;否则,由于并发模式失败,应用程序将观察到更长的暂停。有几种方法可以启动并发收集。

根据最近的历史,CMS 收集器维护对老年代耗尽之前剩余时间的估计以及并发收集周期所需时间的估计。使用这些动态估计,并发收集周期开始,目的是在老年代耗尽之前完成收集周期。为了安全起见,这些估计值被填充,因为并发模式故障可能非常昂贵。

如果老年代的占用率超过初始占用率(老年代的百分比),也会启动并发收集。此初始占用率阈值的默认值约为 92%,但该值可能会因版本而异。可以使用命令行选项手动调整此值-XX:CMSInitiatingOccupancyFraction=,其中是老年代大小的整数百分比(0 到 100)。

7.8 暂停调度

年轻代收集老年代收集暂停是独立发生的。

它们不重叠,但可能会快速连续发生,因此一个垃圾收集的暂停,紧接着另一个集合的暂停,可能看起来是一个较长的暂停。为了避免这种情况,CMS 收集器尝试将暂停安排在上一个和下一个年轻代暂停之间的大致中间。目前还没有针对初始标记暂停进行此调度,这通常比重新标记暂停要短得多。

7.9 并发标记扫描收集器测量

以下是带有选项的 CMS 收集器的输出-Xlog:gc:

[121,834s][info][gc] GC(657) Pause Initial Mark 191M->191M(485M) (121,831s, 121,834s) 3,433ms
[121,835s][info][gc] GC(657) Concurrent Mark (121,835s)
[121,889s][info][gc] GC(657) Concurrent Mark (121,835s, 121,889s) 54,330ms
[121,889s][info][gc] GC(657) Concurrent Preclean (121,889s)
[121,892s][info][gc] GC(657) Concurrent Preclean (121,889s, 121,892s) 2,781ms
[121,892s][info][gc] GC(657) Concurrent Abortable Preclean (121,892s)
[121,949s][info][gc] GC(658) Pause Young (Allocation Failure) 324M->199M(485M) (121,929s, 121,949s) 19,705ms
[122,068s][info][gc] GC(659) Pause Young (Allocation Failure) 333M->200M(485M) (122,043s, 122,068s) 24,892ms
[122,075s][info][gc] GC(657) Concurrent Abortable Preclean (121,892s, 122,075s) 182,989ms
[122,087s][info][gc] GC(657) Pause Remark 209M->209M(485M) (122,076s, 122,087s) 11,373ms
[122,087s][info][gc] GC(657) Concurrent Sweep (122,087s)
[122,193s][info][gc] GC(660) Pause Young (Allocation Failure) 301M->165M(485M) (122,181s, 122,193s) 12,151ms
[122,254s][info][gc] GC(657) Concurrent Sweep (122,087s, 122,254s) 166,758ms
[122,254s][info][gc] GC(657) Concurrent Reset (122,254s)
[122,255s][info][gc] GC(657) Concurrent Reset (122,254s, 122,255s) 0,952ms
[122,297s][info][gc] GC(661) Pause Young (Allocation Failure) 259M->128M(485M) (122,291s, 122,297s) 5,797ms

657 CMS Full GC主要是如下过程:

  • 初始标记(CMS initial mark)
  • 并发标记(CMS consuurrent mark)
  • Concurrent Preclean(并发预清理)
  • Concurrent Abortable Preclean(可中止的并发预清理)
  • 重新标记(CMS remark)
  • 并发清除(CMS concurrent sweep)
  • Concurrent Reset(并发重置)

GC日志说明:CMS 集合(GC ID 657)的输出与Minor GC(GC ID 658、659 和 660)的输出相互穿插;通常在并发收集周期中会发生许多Minor GC 。暂停初始标记表示并发收集周期的开始。以“Concurrent”开头的行表示并发阶段的开始和结束。暂停重新标记是最后的暂停。之前没有讨论的是Preclean预清洁阶段。Preclean 表示可以同时完成的工作,为重新标记阶段做准备。最后阶段由 Concurrent Reset 指示,并为下一次并发收集做准备。

初始标记暂停时间通常比Minor GC暂停时间短。如 CMS 收集器输出示例所示,并发阶段(并发标记、并发预清理和并发扫描)通常持续时间明显长于Minor GC暂停。但是请注意,在这些并发阶段,应用程序不会暂停。重新标记停顿的长度通常与Minor GC相当。重新标记暂停受某些应用程序特性(例如,对象修改率高会增加此暂停)和自上次Minor GC以来的时间(例如,年轻代中的更多对象可能会增加此暂停)的影响。

技术咨询支持,可以扫描微信公众号进行回复咨询
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宋小生的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值