触发Full GC的时机
由于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的时机的更多相关文章
- 触发Full GC执行的情况
除直接调用System.gc外,触发Full GC执行的情况有如下四种. 1. 旧生代空间不足 旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然 ...
- GC之三--GC 触发Full GC执行的情况及应对策略
1.System.gc()方法的调用 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数. ...
- 触发Full GC执行的情况 以及其它补充信息
除直接调用System.gc外,触发Full GC执行的情况有如下四种.1. 旧生代空间不足旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然不足 ...
- GC的时机
说到JVM,GC(垃圾回收)是非常重要的机制. 那么首先的问题是: GC在什么时候会发生? GC的触发包括两种情况:1.程序调用System.gc()的时候.2.系统自身决定是否需要GC. 系统进行G ...
- GC之八--GC 触发Full GC执行的情况及应对策略
目录: GC之一--GC 的算法分析.垃圾收集器.内存分配策略介绍 GC之二--GC日志分析(jdk1.8)整理中 GC之三--GC 触发Full GC执行的情况及应对策略 gc之四--Minor G ...
- 由「Metaspace容量不足触发CMS GC」从而引发的思考
https://mp.weixin.qq.com/s/1VP7l9iuId_ViP1Z_vCA-w 某天早上,毛老师在群里问「cat 上怎么看 gc」. 好好的一个群 看到有 GC 的问题,立马做出小 ...
- java触发full gc的几种情况概述
前言 近期被问及这个问题,在此记录整理一下. System.gc()方法的调用 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full ...
- Minor GC 和 Full GC的时机
一.对象何时能够进入老年代 GC年龄判定 每进行一次GC过程,存活的对象的GC年龄都会+1:当对象逃过15次GC,年龄达到15岁时,即可进入老年代 可以通过-XX:MaxTenuringThreshl ...
- 触发full gc的条件
1.调用System.gc 2.老年代空间不足 3.永生区空间不足 4.CMS GC时出现promotion failed和concurrent mode failure 5.统计得到的Minor G ...
随机推荐
- C#NPOI.RabbitMQ.EF.Attribute.HttpRuntime.Cache.AD域.List<T>根据指定字段去重.前端JQuery.Cache.I18N(多语言).data-xx(自定义属性)
使用NPOI 操作Excel 个人使用的电脑基本默认安装Excel 操作起来 调用Excel的组件便可.如果是一台服务器.没有安装Excel,也就无法调用Excel组件. 在此推荐第三方插件.NPOI ...
- 「BZOJ 1001」狼抓兔子
题目链接 luogu bzoj \(Solution\) 这个貌似没有什么好讲的吧,直接按照这个给的图建图就好了啊,没有什么脑子,但是几点要注意的: 建双向边啊. 要这么写,中间还要写一个\(whil ...
- Stars in Your Window(线段树求最大矩形交)
题目连接 http://poj.org/problem?id=2482 Description Fleeting time does not blur my memory of you. Can it ...
- Kotlin if else判断
Kotlin的if相对与java,有着较为灵活的用法. if是用来判断. if在Kotlin里面可以作为表达式来使用. 如果熟悉C java C#等 A>B:A?B这个判断应该是很熟悉,而Kot ...
- SKU:唯一标识填什么
策略 随意填写 只要别和别人重复就好 ,不过重复你也创建不了. 最好填与APP信息相关的,比如直接填写bundle ID 上去...跟套装ID保持一致. 你新建应用的时候都还没有APP ID 你怎么填 ...
- Object C语法学习笔记(二)
1.@property与@synthesize配对使用. @property预编译指令的作用是自动声明属性的setter和getter方法. @synthesize 创建了该属性的访问代码 功能:让编 ...
- CPU 的工作原理
内部架构 CPU 的根本任务就是执行指令,对计算机来说最终都是一串由 0 和 1 组成的序列.CPU 从逻辑上可以划分成 3 个模块,分别是控制单元.运算单元和存储单元 .其内部架构如下: [1]控制 ...
- spring boot 自签发https证书
一.使用Jdk自带的工具生成数字证书,如下: Java代码 ./keytool -genkey -v -alias tomcat -keyalg RSA -keystore /root/tomca ...
- 从map中取出最大或最小value对应的key---多种写法
package com.yuwanlong.hashing; import java.util.ArrayList; import java.util.Collections; import java ...
- 2、Tensorflow中的变量
2.Tensorflow中的变量注意:tf中使用 变量必须先初始化下面是一个使用变量的TF代码(含注释): # __author__ = "WSX" import tensorfl ...