由于Full GC的耗时是Minor GC的十倍左右,所以Full GC的频率设计得比Minor GC低得多。现总结一下触发Full GC的情况。

在那些实现了CMS的比较新的虚拟机中,如果配置了-XX:+UseConcMarkSwapGC,则启用CMS回收算法,CMS会周期性地检查老年代的情况,每隔一定时间(默认2秒),就检查是否需要对老年代进行一次CMS回收,判断的依据如下:

1、如果没有设置-XX:+UseCMSInitiatingOccupancyOnly,虚拟机会根据收集的数据决定是否触发(建议线上环境带上这个参数,不然会加大问题排查的难度)。
2、老年代使用率达到阈值 CMSInitiatingOccupancyFraction,默认92%。
3、永久代的使用率达到阈值 CMSInitiatingPermOccupancyFraction,默认92%,前提是开启 CMSClassUnloadingEnabled
4、新生代的晋升担保失败。
 

CMS分为两种模式,background和foreground,background采用concurrent remark模式,可以和用户进程并行,而foreground则必须要stop the world(STW)。周期性的CMS采用的是background的方式,而主动的GC则采用foreground方式。主动的GC肯定是Full GC,反之则未必,因为Full GC不是只在CMS中存在的,并且Full GC也可以是并行的Full GC(区别于正常的Full GC),采用并行的Full GC在Old GC阶段走的是background式的CMS,可参考寒泉子《jvm源码分析之SystemGC完全解读》一文。本文的重点也是Full GC。

因为Full GC所用的时间较长,为了充分发挥CMS的优势,通常都会配置-XX:+UseCMSInitiatingOccupancyOnly,让CMS周期性的以和用户现场并行的方式进行垃圾回收,这也是CMS设计的初衷。

但是呢,因为CMS采用标记-清理的方式进行GC,所以会产生碎片,时间久了,碎片就会很多,所以一般来说,进行了一段时间CMS之后,如果开启了UseCMSCompactAtFullCollection(默认为true开启),在foreground的时候就要采用一次压缩,这时采用Serial Old或Parallel Old这些采用标记-整理算法的GC方式(CMS采用的是标记-清理算法)进行回收。具体多少次full gc (foreground CMS)之后进行一次压缩,取决于-XX:CMSFullGCsBeforecompact(默认为0)。源码如下:

*should_compact = UseCMSCompactAtFullCollection && 
((_full_gcs_since_conc_gc >= CMSFullGCsBeforeCompaction)
|| GCCause::is_user_requested_gc(gch->gc_cause())
|| gch->incremental_collection_will_fail(true /* consult_young */)
);

从源码可以看出,除了达到一定次数之外,如果用户调用了System.gc()以及发生了promotion failed,也会进行一次压缩。同时也可以看出,foreground不一定会采用压缩,所以那些说foreground就是mark swap compact(msc)的是不对的。

但是周期性的CMS(background)只会回收老年代,除了周期性的进行GC之外,还有一些紧急情况,需要主动触发GC(foreground),主动触发的GC会连带一次Minor GC,所以也称为Full GC。主动触发的GC是会暂停所有用户现场的,俗称stop the world(STW)。

在那些没有实现CMS的老虚拟机或者没有开启CMS的虚拟机中,每一次Old GC都是Full GC,且会STW,当然因为除了CMS之外,其他的老年代回收算法都是采用标记-整理的方式,所以肯定也是压缩的,。

如果正在进行CMS回收,又触发了一次Full GC,则Full GC会抢占回收执行机会,停止CMS,采用Serial Old或Parallel Old这些采用标记-整理算法的GC方式(CMS采用的是标记-清理算法)进行Full GC。

下面是一些会触发Full GC的情况

1.System.gc()

在没有开启DisableExplicitGC的情况下,虽然只是建议,但是很多情况下,都会调用Full GC的,比如在原本应进行CMS的时候。System.gc()一般都是用在要释放堆外内存的时候使用。

2.老生代内存不足的时候

这种情况通常是对象要晋升到老年代中时,发现老年代的内存不足了,所以要引发一次Full GC。对象的晋升分为正常晋升和提前晋升。

3.永生区空间不足时

有些虚拟机把方法区也放到堆中管理,当加载的类太多时,永生区内存不足需要回收,也会触发Full GC

4.冒险失败之后

在Minor GC时发现to去的内存不足,则将Eden区和from区的内存全部晋升到老年区,清空新生代。但是如果此时老年区内存不足,则会冒险失败,冒险失败之后,对象仍然留在新生代(此时的Eden区和from区都接近99%),然后出发一次Full GC,这样便于下次如果还有冒险,可以增加冒险成功的几率。

5.HandlePromotionFailure设置为false或者历年平均晋升对象的大小大余老年代剩余连续空间

在Minor GC之前,虚拟机会检查老年代剩余连续空间是否大余新生代所有对象总大小,如果大余,则说明Minor GC绝对安全;如果小于,则会检查HandlePromotionFailure设置是否担保失败,如果不担保,则在Minor GC之前进行一次Full GC;如果担保,则再检查历年平均晋升对象的大小是否大余老年代剩余连续空间,如果大余,则不冒险,在Minor GC之前进行一次Full GC;如果小于,则冒险,进入情况4。

6.分配大对象时(和2其实是一样的,但是因为特殊,所以单独拿出来说)

如果直接要分配一个大对象,并且这个大对象的大小超过Eden区的一半,这个对象就会直接分配在老年代,此时如果老年代空间不足,出发一次Full GC,而不出发Minor GC。但是需要注意的是,如果分配的是TLAB而不是真正的大对象,那么不会导致full gc,而是调整TLAB的大小。

7.执行jmap -histo:live或者jmap -dump:live的时候

这属于强制让虚拟机执行一次full GC。

触发Full GC的时机的更多相关文章

  1. 触发Full GC执行的情况

    除直接调用System.gc外,触发Full GC执行的情况有如下四种. 1. 旧生代空间不足 旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然 ...

  2. GC之三--GC 触发Full GC执行的情况及应对策略

    1.System.gc()方法的调用 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数. ...

  3. 触发Full GC执行的情况 以及其它补充信息

    除直接调用System.gc外,触发Full GC执行的情况有如下四种.1. 旧生代空间不足旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然不足 ...

  4. GC的时机

    说到JVM,GC(垃圾回收)是非常重要的机制. 那么首先的问题是: GC在什么时候会发生? GC的触发包括两种情况:1.程序调用System.gc()的时候.2.系统自身决定是否需要GC. 系统进行G ...

  5. GC之八--GC 触发Full GC执行的情况及应对策略

    目录: GC之一--GC 的算法分析.垃圾收集器.内存分配策略介绍 GC之二--GC日志分析(jdk1.8)整理中 GC之三--GC 触发Full GC执行的情况及应对策略 gc之四--Minor G ...

  6. 由「Metaspace容量不足触发CMS GC」从而引发的思考

    https://mp.weixin.qq.com/s/1VP7l9iuId_ViP1Z_vCA-w 某天早上,毛老师在群里问「cat 上怎么看 gc」. 好好的一个群 看到有 GC 的问题,立马做出小 ...

  7. java触发full gc的几种情况概述

    前言 近期被问及这个问题,在此记录整理一下. System.gc()方法的调用 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full ...

  8. Minor GC 和 Full GC的时机

    一.对象何时能够进入老年代 GC年龄判定 每进行一次GC过程,存活的对象的GC年龄都会+1:当对象逃过15次GC,年龄达到15岁时,即可进入老年代 可以通过-XX:MaxTenuringThreshl ...

  9. 触发full gc的条件

    1.调用System.gc 2.老年代空间不足 3.永生区空间不足 4.CMS GC时出现promotion failed和concurrent mode failure 5.统计得到的Minor G ...

随机推荐

  1. Transaction And Lock--快照事务隔离级别

    --================================================--准备数据GOCREATE DATABASE DB5GOUSE DB5GOCREATE TABLE ...

  2. mysql 远程访问不行解决方法 Host is not allowed to connect to this MySQL server

    mysql 远程访问不行解决方法 Host is not allowed to connect to this MySQL server 如果你想连接你的mysql的时候发生这个错误: ERROR 1 ...

  3. 【智能算法】迭代局部搜索(Iterated Local Search, ILS)详解

    迭代局部搜索(Iterated Local Search, ILS) 源代码下载请关注微信公众号[程序猿声],在后台回复:[ILS],不包括[]即可下载. 00 目录 局部搜索算法 简单局部搜索 迭代 ...

  4. SJTU 机试 数学

    题目描述 给定n,a求最大的k,使n!可以被a^k整除但不能被a^(k+1)整除. 输入描述: 两个整数n(2<=n<=1000),a(2<=a<=1000) 输出描述: 一个 ...

  5. NAND NOR Flash 和MTD

    来自:http://blog.sina.com.cn/s/blog_6b489d5e0102xm62.html 一.NAND和NOR Flash 一般来说,快闪记忆体可分为两大规格,一个是NAND, ...

  6. 通过文件路径读取CSV表格内的数据

    ReadDataFromCSV.h UCLASS() class MYPROJECT_API UReadDataFromCSV : public UBlueprintFunctionLibrary { ...

  7. jeesite 的提示消息图标

    jeesite  的提示消息图标 jeesite 框架的提示信息 保存数据时 总是显示一个叉子图标 不符合要求 原因: 不加成功两字:如下 后来大神说 保存数据提示语句必须加“”“成功” 才会出现正确 ...

  8. REST模式中HTTP请求方法(GET,POST,PUT,DELETE)

    一直在测试REST模式的WEB SERVICE接口,客户端的HTTP的请求方式一般分为四种:GET.POST.PUT.DELETE,这四种请求方式有什么不同呢.简单的说,GET就是获取资源,POST就 ...

  9. 洛谷 P4093 [HEOI2016/TJOI2016]序列(Cdq+dp)

    题面 luogu 题解 \(Cdq分治+dp\) \(mx[i],mn[i]\)分别表示第\(i\)位最大,最小能取到多少 那么有 \(j < i\) \(mx[j] \le a[i]\) \( ...

  10. hql语句加别名的错误

    写了一个查询数量的方法,结果执行不出来,debug后是runtimeException,然后就在那个hql里面使劲找,将他翻译成sql在数据库中执行,结果也没问题,原来的hql如下: 注意这个num, ...