热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

频繁gc是什么意思_什么情况下会发生fullGc?如何排查频繁发生fullGc的原因?...

GC就是Java的垃圾回收机制,要了解什么情况下会发生GC(即GC得触发条件),我们需要先了解JVM的内存模型结构,之前一篇文章已经详细讲

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

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

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

>>>>>必须知道的知识点<<<<<

Young space&#xff1a;年轻代(新生代)&#xff0c;保存生命周期较短的对象

Tenured space&#xff1a;老年代(年老代)&#xff0c;保存生命周期较长的对象

Minor GC&#xff1a;发生在Young space中的gc

Major GC&#xff1a;发生在老年代Tenured space中的gc

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

Full GC&#xff1a;无官方定义&#xff0c;通常意义上而言指的是一次特殊GC的行为描述&#xff0c;这次GC会回收整个堆的内存&#xff0c;包含老年代&#xff0c;新生代&#xff0c;metaspace等。

但是实际情况中&#xff0c;我们主要看的是gc.log日志&#xff0c;其中也会发现在部分gc日志头中也有Full GC字眼&#xff0c;此处表示含义是在这次GC的全过程中&#xff0c;都是STW的状态&#xff0c;也就是说在这次GC的全过程中所有用户线程都是处于暂停的状态。

>>>>>年轻代<<<<<

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

为啥默认这个比例&#xff1f;

一般情况下&#xff0c;新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor

GC后&#xff0c;如果仍然存活&#xff0c;将会被移到Survivor区。对象在Survivor区中每熬过一次Minor

GC&#xff0c;年龄就会增加1岁&#xff0c;当它的年龄增加到一定程度(默认15岁)时&#xff0c;就会被移动到年老代中。

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

这个时候&#xff0c;“From”和“To”会交换他们的角色&#xff0c;就是新的“To”是上次GC前的“From”&#xff0c;新的“From”就是上次GC前的“To”。不管怎样&#xff0c;都会保证名为To的Survivor区域是空的。Minor

GC会一直重复这样的过程&#xff0c;直到“To”区被填满&#xff0c;“To”区被填满之后&#xff0c;会将所有对象移动到年老代中。

总结下来&#xff0c;JVM的堆区对象分配的规则一般如下&#xff1a;

1)对象优先在Eden区分配

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

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

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

5)空间分配担保

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

GC的触发条件

PS:JVM优化的目的就是减少SWT执行的时间(避免卡顿)&#xff0c;避免频繁full gc

1)System.gc()方法的调用。

此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定&#xff0c;但很多情况下它会触发 Full GC,从而增加Full

GC的频率&#xff0c;也即增加了间歇性停顿的次数。强烈影响系建议能不使用此方法就别使用&#xff0c;让虚拟机自己去管理它的内存&#xff0c;可通过通过-XX:&#43;

DisableExplicitGC来禁止RMI(Java远程方法调用)调用System.gc。

2)旧生代空间不足。旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象&#xff0c;当执行Full

GC后空间仍然不足&#xff0c;则抛出错误&#xff1a;java.lang.OutOfMemoryError: Java heap space

。为避免以上两种状况引起的FullGC&#xff0c;调优时应尽量做到让对象在Minor

GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。

3)Permanet Generation空间满了。Permanet

Generation中存放的为一些class的信息等&#xff0c;当系统中要加载的类、反射的类和调用的方法较多时&#xff0c;Permanet

Generation可能会被占满&#xff0c;在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full

GC仍然回收不了&#xff0c;那么JVM会抛出错误信息&#xff1a;java.lang.OutOfMemoryError: PermGen space 。为避免Perm

Gen占满造成Full GC现象&#xff0c;可采用的方法为增大Perm Gen空间或转为使用CMS GC。

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

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



推荐阅读
  • JVM:33 如何查看JVM的Full GC日志
    1.示例代码packagecom.webcode;publicclassDemo4{publicstaticvoidmain(String[]args){byte[]arr ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 本文介绍了安全性要求高的真正密码随机数生成器的概念和原理。首先解释了统计学意义上的伪随机数和真随机数的区别,以及伪随机数在密码学安全中的应用。然后讨论了真随机数的定义和产生方法,并指出了实际情况下真随机数的不可预测性和复杂性。最后介绍了随机数生成器的概念和方法。 ... [详细]
  • ShiftLeft:将静态防护与运行时防护结合的持续性安全防护解决方案
    ShiftLeft公司是一家致力于将应用的静态防护和运行时防护与应用开发自动化工作流相结合以提升软件开发生命周期中的安全性的公司。传统的安全防护方式存在误报率高、人工成本高、耗时长等问题,而ShiftLeft提供的持续性安全防护解决方案能够解决这些问题。通过将下一代静态代码分析与应用开发自动化工作流中涉及的安全工具相结合,ShiftLeft帮助企业实现DevSecOps的安全部分,提供高效、准确的安全能力。 ... [详细]
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了Windows Vista操作系统中的用户账户保护功能,该功能是为了增强系统的安全性而设计的。通过对Vista测试版的体验,可以看到系统在安全性方面的进步。该功能的引入,为用户的账户安全提供了更好的保障。 ... [详细]
  • Apache Shiro 身份验证绕过漏洞 (CVE202011989) 详细解析及防范措施
    本文详细解析了Apache Shiro 身份验证绕过漏洞 (CVE202011989) 的原理和影响,并提供了相应的防范措施。Apache Shiro 是一个强大且易用的Java安全框架,常用于执行身份验证、授权、密码和会话管理。在Apache Shiro 1.5.3之前的版本中,与Spring控制器一起使用时,存在特制请求可能导致身份验证绕过的漏洞。本文还介绍了该漏洞的具体细节,并给出了防范该漏洞的建议措施。 ... [详细]
author-avatar
mobiledu2502894453
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有