JVM 源码解读之 CMS 何时会进行 Full GC

栏目: Java · 发布时间: 5年前

内容简介:本文内容是基于 JDK 8在文章此压缩式 GC,CMS 使用的是跟 Serial Old GC 一样的 LISP2 算法,其使用 mark-compact 来做 Full GC,一般称之为 MSC(mark-sweep-compact),它收集的范围是 Java 堆的 Young Gen 和 Old Gen 以及 metaspace(元空间)。

点击上方" 涤生的博客 ",关注我

转载请注明原创出处,谢谢! 如果读完觉得有收获的话,欢迎点赞加关注。

前言

本文内容是基于 JDK 8

在文章 JVM 源码解读之 CMS GC 触发条件 中分析了 CMS GC 触发的五类情况,并且提到 CMS GC 分为 foreground collector 和 background collector。 不管是 foreground collector 还是 background collector 使用的都是 mark-sweep 算法,分阶段进行标记清理,优点很明显-低延时,但最大的缺点是存在碎片,内存空间利用率低。因此,CMS 为了解决这个问题,在每次进行 foreground collector 之前,判断是否需要进行一次压缩式 GC。

此压缩式 GC,CMS 使用的是跟 Serial Old GC 一样的 LISP2 算法,其使用 mark-compact 来做 Full GC,一般称之为 MSC(mark-sweep-compact),它收集的范围是 Java 堆的 Young Gen 和 Old Gen 以及 metaspace(元空间)。

本文不涉及具体的收集过程,只分析 CMS 在什么情况下会进行 compact 的 Full GC。

什么情况下会进行一次压缩式 Full GC 呢?

何时会进行 FullGC?

下面这段代码就是 CMS 进行判断是进行 mark-sweep 的 foreground collector,还是进行 mark-sweep-compact 的 Full GC。主要的判断依据就是是否进行压缩,即代码中的 should_compact。

接下来我们就来分析下在什么情况下会进行 compact, 来看 decide foreground collection_type 函数,主要分为 4 种情况:

  1. GC(包含 foreground collector 和 compact 的 Full GC)次数

  2. GCCause 是否是用户请求式触发导致的

  3. 增量 GC 是否可能会失败(悲观策略)

  4. 是否清理所有 SoftReference

接下来我们具体看每种情况

1. GC(包含 foreground collector 和 compact 的 Full GC)次数

这里说的 GC 次数 full gcs since conc_gc,指的是从上次 background collector 后,foreground collector 和 compact 的 Full GC 的次数,只要次数大于等于 CMSFullGCsBeforeCompaction 参数阈值,就表示可以进行一次压缩式的 Full GC。 ( CMSFullGCsBeforeCompaction 参数默认是 0,意味着默认是要进行压缩式的 Full GC

2. GCCause 是否是用户请求式触发导致

用户请求式触发导致的 GCCause 指的是 java lang system gc(即 System.gc())或者 jvmti force_gc(即 JVMTI 方式的强制 GC) 意味着只要是 System.gc(前提没有配置 ExplicitGCInvokesConcurrent 参数)调用或者 JVMTI 方式的强制 GC 都会进行一次压缩式的 Full GC

3. 增量 GC 是否可能会失败(悲观策略)

JVM 源码解读之 CMS GC 触发条件 文章中也提到了这块内容, 指的是两代的 GC 体系中,主要指的是 Young GC 是否会失败。如果 Young GC 已经失败或者可能会失败,CMS 就认为可能存在碎片导致的,需要进行一次压缩式的 Full GC。

“incremental collection failed()” 这里指的是 Young GC 已经失败,至于 为什么会失败一般是因为 Old Gen 没有足够的空间来容纳晋升的对象,比如常见的 “promotion failed” 。

“!get gen(0)->collection attempt is safe()” 指的是 Young Gen 存活对象晋升是否可能会失败。 通过判断当前 Old Gen 剩余的空间大小是否足够容纳 Young GC 晋升的对象大小。 Young GC 到底要晋升多少是无法提前知道的, 因此,这里通过统计平均每次 Young GC 晋升的大小和当前 Young GC 可能晋生的最大大小来进行比较。

下面展示的就是 collection attempt is_safe 函数的代码:

4. 是否清理所有 SoftReference

SoftReference 软引用,你应该了解它的特性,一般是在内存不够的时候,GC 会回收相关对象内存。 这里说的就是需要回收所有软引用的情况,在配置了 CMSCompactWhenClearAllSoftRefs 参数的情况下,会进行一次压缩式的 Full GC。

JDK 1.9 有变更: 彻底去掉了 CMS forground collector 的功能,也就是说除了 background collector,就是压缩式的 Full GC。自然(UseCMSCompactAtFullCollection、CMSFullGCsBeforeCompaction 这两个参数也已经不在支持了。

总结

本文着重介绍了 CMS 在以下 4 种情况:

  • GC(包含 foreground collector 和 compact 的 Full GC)次数

  • GCCause 是否是用户请求式触发导致

  • 增量 GC 是否可能会失败(悲观策略)

  • 是否清理所有 SoftReference

会进行压缩式的 Full GC,并且详细介绍了每种情况下的触发条件。 我们在 GC 调优时应该尽可能的避免压缩式的 Full GC,因为其使用的是 Serial Old GC 类似算法,它是单线程对全堆以及 metaspace 进行回收,STW 的时间会特别长,对业务系统的可用性影响比较大。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

微积分的历程

微积分的历程

William Dunham / 李伯民、汪军、张怀勇 / 人民邮电出版社 / 2010-8 / 29.00元

“微积分”这一名称最早出现在哪本书中?第一本微积分教科书又是谁人所写?微积分究竟是谁人发明的?著名的洛必达法则居然是伯努利的研究成果?谁被誉为“分析学的化身”?谁又被誉为“现代分析学之父”?哪些数学天才使微积分的创建过程终于画上完美的句号?……本书将带你一一探究上述问题。 本书宛如一座陈列室,汇聚了十多位数学大师的杰作,当你徜徉其中时会对人类的想象力惊叹不已,当你离去时必然满怀对天才们的钦佩......一起来看看 《微积分的历程》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码