GC就是Java的垃圾回收机制,要了解什么情况下会发生GC(即GC得触发条件),我们需要先了解JVM的内存模型结构,之前一篇文章已经详细讲解了Jvm的内存模型结构,而通常来说,GC主要针对的是堆(java heap)区。

而java heap是分代的(年轻代和老年代),为什么要分代?其实也不难理解,分代就是为了优化性能,如果不分代,那就会导致所有对象揉在一块,那样GC就会对堆区域进行全扫描。所以,分代可以大大提升GC性能,那么,分代的原理是什么?

JVM对于堆的垃圾回收,采用分代收集的策略,所以分代的原理就是根据堆中对象的存活周期进行分代,年轻代中,每次垃圾回收都有大批对象死去,只有少量存活,而老年代中存放的对象存活率高。

>>>>>必须知道的知识点<<<<<
Young space:年轻代(新生代),保存生命周期较短的对象

Tenured space:老年代(年老代),保存生命周期较长的对象

Minor GC:发生在Young space中的gc

Major GC:发生在老年代Tenured space中的gc

STW(stop the world):指的是用户线程在运行至安全点(safe point)或安全区域(safe region)之后,就自行挂起,进入暂停状态,对外的表现就是卡顿,而不论何种gc算法,不论是minor gc还是major gc都会STW,区别只在于STW的时间长短。

Full GC:无官方定义,通常意义上而言指的是一次特殊GC的行为描述,这次GC会回收整个堆的内存,包含老年代,新生代,metaspace等。
但是实际情况中,我们主要看的是gc.log日志,其中也会发现在部分gc日志头中也有Full GC字眼,此处表示含义是在这次GC的全过程中,都是STW的状态,也就是说在这次GC的全过程中所有用户线程都是处于暂停的状态。

>>>>>年轻代<<<<<
Jvm把年轻代分三部分:1个Eden(伊甸园)区和2个Survivor(幸存者)区(分别叫from和to),默认比例为8:1。

为啥默认这个比例?
一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度(默认15岁)时,就会被移动到年老代中。

因为年轻代中的对象基本都是朝生夕死的(80%以上),所以年轻代的垃圾回收算法采用复制算法(内存分为两块,每次只用其中一块,当一块内存用完,就将还活着的对象复制到另外一块内存上,复制算法不产生内存碎片)。在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。

这个时候,“From”和“To”会交换他们的角色,就是新的“To”是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

总结下来,JVM的堆区对象分配的规则一般如下:
1)对象优先在Eden区分配

2)大对象直接进入老年代(-XX:PretenureSizeThreshold=3145728 该参数来定义进入老年代对象大小)

3)长期存活的对象将进入老年代(在JDK8中-XX:MaxTenuringThreshold=1的阀值设定根本没用)

4)动态对象年龄判定(虚拟机并不会永远地要求对象的年龄都必须达到MaxTenuringThreshold才能晋升老年代,如果Survivor空间中相同年龄的所有对象的大小总和大于Survivor的一半,年龄大于或等于该年龄的对象就可以直接进入老年代)

5)空间分配担保

6)只要老年代的连续空间大于(新生代所有对象的总大小或者历次晋升的平均大小)就会进行minor GC,否则会进行full GC

GC的触发条件
PS:JVM优化的目的就是减少SWT执行的时间(避免卡顿),避免频繁full gc
1)System.gc()方法的调用。
此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数。强烈影响系建议能不使用此方法就别使用,让虚拟机自己去管理它的内存,可通过通过-XX:+ DisableExplicitGC来禁止RMI(Java远程方法调用)调用System.gc。

2)旧生代空间不足。旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出错误:java.lang.OutOfMemoryError: Java heap space 。为避免以上两种状况引起的FullGC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。

3)Permanet Generation空间满了。Permanet Generation中存放的为一些class的信息等,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出错误信息:java.lang.OutOfMemoryError: PermGen space 。为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC。

4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代可用内存不足(老年代可用内存小于该对象)

什么情况下会发生full Gc?如何排查频繁发生full Gc的原因?相关推荐

  1. Goroutine调度时机-什么时候和什么情况下会发生调度?

    原文地址:Goroutine调度时机-什么时候和什么情况下会发生调度? Go调度器会在以下三种情况对goroutine进行调度: goroutine执行某个操作因条件不满足需要等待而发生的调度. go ...

  2. 线上频繁发生Full GC 如何调优?如何快速定位OOM、cpu飙升、线程死锁等问题

    文章目录 1. jvm调优命令.工具介绍 ①:jps ②:jmap 查看应用中各实例生成情况 快速定位内存突然飙升导致的OOM异常 查看堆内存使用情况 ③:Jstack 检测线程死锁 快速定位导致cp ...

  3. 什么情况下会发生Full GC?

    1.调用System.gc()时 当调用System.gc()时,是建议JVM进行Full GC,只是建议,不是一定会发生,但一般情况下,JVM也会进行Full GC,进行Full GC时会让用户线程 ...

  4. 038、JVM实战总结:200小时积累,6小时烹制,史上最强图,图解:大厂面试题,Young GC和Full GC分别在什么情况下会发生?

    今天学习本讲,按照艾宾浩斯遗忘曲线应该复习:37 35 31 24 9.建议大家按照遗忘曲线来复习学过的内容. 这是本人花了6个小时,精心绘制的"垃圾回收"活动图,同时进行了文字总 ...

  5. 史上最强图,图解:大厂面试题,Young GC和Full GC分别在什么情况下会发生?

    在原文基础上重新绘制了一下进行Young GC .Full GC 的条件及处理过程(原文链接 https://blog.csdn.net/dingshuo168/article/details/987 ...

  6. 040、JVM实战总结:案例实战:每日百亿数据量的实时分析引擎,为啥频繁发生Full GC ?

    1.上文案例再分析 2.一个日处理上亿数据的计算系统 MySQL数据库以及其他数据源里提取大量的数据加载到自己的JVM内存里来进行计算处理. 总负载:每分钟大概需要执行500次数据提取和计算的任务   ...

  7. 什么是跨域?什么情况下会发生跨域请求?

    跨域,指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器施加的安全限制. 同源策略:所谓同源是指:协议,域名,端口均相同.即便两个不同的域名指向同一个ip地址,也非同源. ht ...

  8. 并发insert情况下会发生重复的数据插入问题

    1.背景 用多线程接收推送的订单数据,把接收的订单数据存到一个表中,实现的需求是:如果接收的订单消息在数据库中已经存在,那么执行update操作:如果没有存在,那么执行insert操作 代码逻辑: i ...

  9. c语言浮点乘法 溢出,浮点加减乘除运算各在什么情况下会发生溢出?

    满意答案 w9o7w429 2014.01.10 采纳率:52%    等级:12 已帮助:2903人 溢出的原因只有一个 那就是这句 c=a/b 其中b的值为0 也就是 b=cint(request ...

最新文章

  1. python功能强大的库_2018 年最受欢迎的15个顶级 Python 库
  2. 第十一天-《企业应用架构模式》-对象-关系行为模式
  3. 学习压缩感知比较好的文章链接收藏
  4. 转:GridView 中如何给删除按钮添加提示
  5. SpringBoot引用lombok让代码更简洁
  6. 深度学习相关资料总结
  7. USACO_2_3_Controlling Companies
  8. java的语法结构_Java中的语法规范语法结构
  9. 【Python】参考ggplot2,Seaborn将迎来超大版本更新!
  10. 大牛深入讲解!高并发你真的理解透彻了吗
  11. vector 使用 c++11 Lambda 表达式 排序
  12. LintCode_514 Paint Fence
  13. C盘的“压缩驱动器以节约磁盘空间”有用吗
  14. 【小知识点】分类机器学习中,某一标签占比太大(标签稀疏),如何学习?...
  15. Android 自定义View关于measure流程的基本思路整理
  16. 手机mtkcdc端口如何开启_MTK驱动安装教程(手机黑屏刷机)
  17. 试验设计第二版茆诗松课后题答案_茆诗松数理统计学答案
  18. [kubernetes]-kubernetes+nfs创建高可用mysql
  19. Nginx安装SSL证书
  20. Matlab c2d离散用法

热门文章

  1. Lua中的userdata
  2. 用lru_cache提高性能
  3. python性能测试可视化_locust安装及其简单使用----基于python的性能测试工具
  4. pxl软件怎么安装? 直接用iTunes就行!
  5. Python 获取指定模块基址
  6. 性能测试第二篇—性能测试指标
  7. IOS Swift5 WkWebView 跳转网页后 加载页面结果方法拦截(WKNavigationResponse)
  8. 质量保障之路:达达测试团队成长记
  9. java面向对象程序设计 习题答案_Java面向对象程序设计习题解答与实验 张桂珠.pdf...
  10. 【ARM】使用Busybox构建根文件系统