Full GC的认识、预防和定位

简介: (/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨ 👀👀👀 个人博客:小奥的博客 👍👍👍:个人CSDN ⭐️⭐️⭐️:传送门 🍹 本人24应届生一枚,技术和

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨ 👀👀👀 个人博客:小奥的博客 👍👍👍:个人CSDN ⭐️⭐️⭐️:传送门 🍹 本人24应届生一枚,技术和水平有限,如果文章中有不正确的内容,欢迎多多指正! 📜 欢迎点赞收藏关注哟! ❤️

文章目录

JVM之带你认识Full GC一. 主要的GC形式1.1 新生代GC(Minor GC)触发机制1.2 老年代GC(Major GC 、Full GC)触发机制

二、Full GC的一些问题2.1 Full GC对程序的影响2.2 如何防止Full GC2.3 如何定位Full GC

三、一些参考案例

JVM之带你认识Full GC

一. 主要的GC形式

JVM在进行GC时,并非每次都对所有内存区域进行垃圾回收,大部分回收的都是指新生代。

针对Hotspot VM的实现,它里面的GC按照回收区域又分为两大种类型:一种是部分收集(Partial GC),一种是整堆收集(Full GC)。

部分收集(Partial GC):不是完整收集整个Java堆的垃圾收集。其中又分为:

新生代收集(Minor GC / Young GC):只是新生代的垃圾收集

老年代收集(Major GC / Old GC):只是老年代的圾收集。

目前,只有CMS GC会有单独收集老年代的行为。

注意,很多时候Major GC会和Full GC混淆使用,需要具体分辨是老年代回收还是整堆回收。

混合收集(MixedGC):收集整个新生代以及部分老年代的垃圾收集。

目前,只有G1 GC会有这种行为 整堆收集(Full GC):收集整个java堆和方法区的垃圾收集。

1.1 新生代GC(Minor GC)触发机制

当新生代空间不足时,就会触发Minor GC,这里的新生代空间不足是指Eden区满,Survivor区满不会引发GC。(每次Minor GC会清理年轻代的内存)因为Java对象大多数都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。Minor GChi引发 STW,暂停用户其他线程,等垃圾回收结束,才会恢复用户线程。

1.2 老年代GC(Major GC 、Full GC)触发机制

(1)Major GC触发时机

出现了Major GC,经常会伴随至少一次的Minor GC。也就是说老年代空间不足时,会现场时触发Minor GC,如果之后空间还不足,则触发Major GC。Major GC的速度一般比Minor GC慢10倍以上,STW的时间更长。如果Major GC后,内存还不足,则会产生OOM异常。

(2)Full GC触发时机

调用System.gc()时,系统建议执行Full GC,但是不一定会执行。老年代空间不足时方法区空间不足时通过Minor GC后进入老年代的平均大小大于老年代的可用内存由Eden区、survivor space0(From Space)区向survivor space1(To Space)区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

二、Full GC的一些问题

2.1 Full GC对程序的影响

Full GC产生的影响主要是:

在发生FULL GC的时候,意味着JVM会安全的暂停所有正在执行的线程(Stop The World),来回收内存空间,在这个时间段内,所有除了回收垃圾的线程外,其他有关JAVA的程序,代码都会静止,反映到系统上,这个过程会导致应用程序暂停执行,造成一定的性能损失和响应延迟。

比如会产生如下的问题:

CPU满载告警API响应时间过长内存反复波动fullgc告警

2.2 如何防止Full GC

《深入理解JVM虚拟机》中给出了这样的建议:

控制Full GC频率的关键是老年代的相对稳定,这主要取决于应用中绝大多数对象能否符合“朝生夕灭”的原则,即大多数对象的生存时间不应当太长,尤其是不能有成批量的、长生存时间的大对象产生,这样才能保障老年代空间的稳定。

所以总结下来,在实际的工作中,我们尽量减少短时间内大量对象的产生,比如重复利用的对象我们可以使用单例模式来减少重复创建,尽量保证老年代的稳定。

2.3 如何定位Full GC

线上服务的GC问题,是Java程序非常典型的一类问题,但是对于经验不足的我们来说还是比较难的,所以我带大家一起学习下,如何系统地定位Full GC的问题。

这里给大家推荐一篇实战排查的文章,博主也是通过这篇文章来学习的。

线上服务的Full GC问题排查,看这篇就够了!

大致的步骤就是:

首先查看我们JVM的配置通过内存分析工具查看老年代的内存变化,排查是内存泄漏还是内存溢出通过jmp查看内存映射信息进一步查看dump内存文件进行分析通过代码分析具体的对象

另外我们一般可以使用一些工具来进行辅助排查问题:

jps: 查看本机java进程jstack: 打印线程的栈信息,制作线程dump文件jmap:打印内存映射信息,制作堆dump文件jstat:性能监控工具jhat:内存分析工具,用于解析堆dump文件并以适合人阅读的方式展示出来jconsole: 简易的jvm可视化工具

这些工具主要是可以查看dump映射文件,从而排查到具体的对象,进而我们再结合代码进行检查即可。

三、一些参考案例

生产大文件下载导致 OOM,顺藤摸瓜拿下