(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨
👀👀👀 个人博客:小奥的博客
👍👍👍:个人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 GC
- 2.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映射文件,从而排查到具体的对象,进而我们再结合代码进行检查即可。