Full GC的认识、预防和定位

本文详细介绍了JVM中的FullGC过程,包括新生代和老年代GC的触发机制,以及FullGC对程序性能的影响。同时提供了防止FullGC的建议和定位FullGC问题的方法,包括使用工具进行内存分析和故障排查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

R 大的回答

二、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映射文件,从而排查到具体的对象,进而我们再结合代码进行检查即可。

三、一些参考案例

04-02
### Full GC 的定义 在 Java 中,Full GC 是指垃圾回收器对整个堆内存(包括年轻代老年代)以及方法区进行全面清理的过程。通常情况下,GC 主要集中在年轻代上执行 Minor GC,而当对象无法放入年轻代或者需要分配较大的对象时,则会触发 Full GC[^1]。 Full GC 可能由多种原因引起,例如老年代空间不足、永久代/元空间满载、System.gc() 被显式调用等。每次发生 Full GC 都会对应用程序性能造成显著影响,因为它会导致应用线程暂停(Stop-The-World),直到完成所有的垃圾回收操作为止。 --- ### 解决 Full GC 问题的方法 #### 方法一:分析内存泄漏 如果程序存在内存泄漏,可能会频繁触发 Full GC。为了检测是否存在内存泄漏,可以使用工具如 JConsole 或者 VisualVM 来监控 JVM 堆内存的变化趋势。此外,还可以通过以下方式定位问题: - 使用 `jmap` 工具生成堆转储文件并利用 `jhat` 进行分析。 - 如果怀疑某些大对象未被销毁,可以通过启用 `-XX:+HeapDumpOnOutOfMemoryError` 参数,在 OOM 发生时自动生成堆转储文件以便后续排查[^2]。 #### 方法二:调整 JVM 参数优化 GC 行为 合理配置 JVM 启动参数能够有效减少 Full GC 的频率及其带来的停顿时间。常见的做法有以下几个方面: - **增大堆大小**:适当增加最大堆容量 (`-Xmx`) 初始堆容量 (`-Xms`) ,从而降低因内存紧张而导致的 Full GC 次数。 - **选用合适的收集器**:针对不同应用场景选择恰当类型的垃圾回收算法,比如 G1 收集器适合处理大规模数据集的应用场景;CMS(Concurrent Mark Sweep)则适用于低延迟需求较高的环境。 - **调节新生代比例**:通过设置 `-XX:NewRatio=N` 控制新生代相对于整个堆的比例,默认值通常是 2 (即新生代占总堆的一半)。对于创建短生命周期临时对象较多的情况可考虑减小该数值来扩大新生代区域范围。 #### 方法三:避免不必要的引用保留 长时间持有无用的对象引用也是引发 Full GC 的常见原因之一。因此建议开发者遵循如下原则以改善此状况: - 定期释放不再使用的资源实例变量。 - 对于缓存机制中的条目设定合理的过期策略及时淘汰陈旧项。 - 尽量采用弱引用(WeakReference)/软引用(SoftReference)代替强引用存储可能很快会被丢弃的数据结构成员[^3]。 #### 方法四:理解 C++ Java 在内存管理上的差异 值得注意的是,虽然两者都涉及到了自动化的内存管理过程,但是它们实现的具体细节却有很大区别。例如,在 C++ 中允许程序员定义析构函数用于手动控制资源释放时机;而在 Java 当中由于引入了垃圾回收机制所以无需担心此类问题[^4] 。然而这也意味着开发人员必须更加关注如何编写高效且不会干扰到正常运行状态下的代码逻辑设计思路。 --- ### 总结 综上所述,解决 Full GC 问题是提升 Java 应用性能的重要环节之一。这不仅涉及到深入理解其背后的工作原理还需要掌握一系列实用技巧来进行针对性调试与优化工作。只有这样才能真正达到既满足业务功能又兼顾用户体验双重目标的最佳效果。 ```bash # 示例命令行查看当前 JVMGC 日志信息 java -verbose:gc -Xloggc:/path/to/gc.log YourApplicationClass ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值