Java线上频繁FullGC的完整排查流程

 更新时间:2026年06月05日 09:33:01   作者:码不停蹄的玄黓  
这段文章详细介绍了FullGC的的常见触发原因原因、排查思路和优化方法,涵盖老年代不足、内存泄漏、MetaSpace元空间满等方面,并提供了从紧急应急到长期优化的全面解决方案,需要的朋友可以参考下

一、先明确:FullGC触发常见原因

  1. 老年代空间不足、内存泄漏/内存溢出
  2. 大对象直接进老年代、频繁晋升
  3. MetaSpace元空间满、动态加载类过多
  4. System.gc()代码主动调用、RMI定时FullGC
  5. JVM参数不合理:新生代太小、Survivor过小、晋升阈值异常
  6. 堆内存分配过小、物理内存被其他进程抢占

核心排查思路:先抓现场 → 看GC日志定位类型 → 堆快照分析 → 代码定位 → 压测复现 → 调参优化

二、阶段1:紧急应急(线上不能停服优先)

1. 基础信息采集

# 查看java进程PID
jps -l
# 实时看GC状态
jstat -gcutil PID 1000

重点指标:

  • O(老年代使用率)持续上涨 → 内存泄漏/对象不停晋升到老年代
  • M(元空间)持续涨满 → 类加载泄漏
  • S0/S1长期几乎满、Eden快速打满 → 新生代过小,对象频繁提前晋升老年代

2. 临时规避(业务优先保可用)

  1. 临时扩容-Xmx/-Xms,增大堆,缓解频繁FGC
  2. 临时关闭RMI自动FullGC:-Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
  3. 临时下线可疑定时任务、批量导入、大文件解析接口

三、阶段2:采集GC日志,定位FGC根因分类

1. 开启/导出GC日志(没提前配置则动态抓取)

JVM启动参数必备(生产标配):

-Xloggc:/xxx/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC

根据GC日志区分4大类FGC:

  1. 老年代占满触发FGC(最常见)
    日志关键字:Allocation Failure,Eden耗尽→对象晋升老年代,老年代不足触发FullGC
  2. MetaSpace满触发FGC
    日志:Metaspace allocation failure,动态代理、热加载、频繁创建ClassLoader
  3. System.gc()主动触发
    日志:Full GC (System.gc()),代码/第三方包显式调用System.gc()
  4. CMS并发失败/晋升担保失败(CMS收集器)
    concurrent mode failure / promotion failed:老年代预留空间不足,担保失败触发STW FullGC

四、阶段3:dump堆快照,定位占用内存的对象(核心步骤)

抓堆时机:FGC频繁、老年代占用率80%+还没OOM时dump,避免OOM后数据丢失

方式1:命令行dump

jmap -dump:format=b,file=heap.hprof PID
# 生产dump建议加参数,不阻塞业务:
jmap -dump:live,format=b,file=heap.hprof PID

方式2:OOM自动dump(提前配置)

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/xxx/heap.hprof

堆文件分析工具

  1. MAT(Eclipse Memory Analyzer,首选)
    • Leak Suspects:泄漏可疑报告(一键定位泄漏对象)
    • Dominator Tree:支配树,查看占用堆最多的对象
    • Histogram:按类统计实例数量、占用内存
  2. JProfiler、Arthas在线分析(不用下载大hprof)

五、阶段4:Arthas在线实时排查(不用重启、不用dump大文件)

1. 安装启动Arthas

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

常用排查命令

# 1. 实时监控GC
gc -i 1000
# 2. 查看堆内存实时分布
heapdump --live /tmp/dump.hprof
# 3. 查看对象实例数量,快速找暴涨对象
dashboard
# 4. 追踪创建大量对象的方法
trace 全类名 方法名
# 5. 排查ClassLoader泄漏
classloader

六、阶段5:按场景逐个定位代码问题

场景1:内存泄漏(老年代缓慢涨,每次FGC回收不掉多少内存)

常见泄漏点:

  1. 静态集合(static List/Map)无限add对象,无移除逻辑
  2. ThreadLocal使用完未remove,线程池复用线程导致对象常驻
  3. 连接池、缓存(本地Cache)无过期淘汰,数据只增不减
  4. 第三方框架:Mybatis拦截器、定时任务、异步线程未销毁对象

MAT定位:支配树找到超大对象 → 查看引用链Reference Chain → 找到业务代码

场景2:大对象频繁创建直接进老年代

  • 一次性读取超大文件、全表查数据库不分页返回全量List
  • 超大字符串拼接、一次性创建超大数组
    JVM参数:-XX:PretenureSizeThreshold=2M 超过阈值直接进老年代,频繁创建触发FGC

场景3:元空间满FGC

  • 动态生成代理类(CGLIB频繁创建)、Groovy脚本热加载
  • 自定义ClassLoader不停新建不卸载,-XX:MaxMetaspaceSize配置过小

场景4:代码主动System.gc()

  1. 第三方SDK、老版本RPC、定时任务里隐式调用System.gc()
  2. 代码检索System.gc()全局关键字,使用Arthas watch拦截调用

七、阶段6:JVM参数优化(分收集器:G1/CMS/ZGC)

通用优化方向

  1. 新生代大小:Eden占堆1/3~1/2,避免Eden过小频繁晋升
  2. 调整SurvivorRatio、MaxTenuringThreshold晋升年龄,减少过早晋升到老年代
  3. 禁用显式GC:-XX:+DisableExplicitGC(谨慎:NIO依赖System.gc堆外内存则不能加)
  4. 合理设置MetaSpace:-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M

G1收集器(主流生产)

-XX:+UseG1GC
-XX:MaxGCPauseMillis=200 # 预期STW停顿
-XX:G1HeapRegionSize=16M

CMS老项目优化

  • 调高老年代预留空间:-XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly,避免并发失败FullGC

八、阶段7:复现验证+上线落地优化

  1. 本地/测试环境压测(JMeter)复现FGC,修复代码后压测验证GC平稳
  2. 上线灰度发布,上线后持续监控GC指标(Prometheus+Grafana)
  3. 告警配置:老年代使用率>80%、10min内FullGC>3次触发告警

九、排查速记口诀

先jstat看GC趋势 → 拉GC日志分FGC类型 → arthas在线查对象 → dump堆MAT找泄漏引用 → 改代码+调JVM参数 → 压测验证上线

到此这篇关于Java线上频繁FullGC的完整排查流程的文章就介绍到这了,更多相关Java线上频繁FullGC内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决idea无法导入识别本地类的问题

    解决idea无法导入识别本地类的问题

    今天做实验不知道按了哪里不能导入识别本地的类,只有jar包的类,百度搜索也没有找到合理的解决方案,经过朋友援助问题根源找到,下面小编把解决方法分享给大家,需要的朋友参考下吧
    2021-08-08
  • Spring Security如何基于Authentication获取用户信息

    Spring Security如何基于Authentication获取用户信息

    这篇文章主要介绍了Spring Security如何基于Authentication获取用户信息,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • java实现XML增加元素操作简单示例

    java实现XML增加元素操作简单示例

    这篇文章主要介绍了java实现XML增加元素操作,结合简单实例形式分析了java针对xml格式数据的读取、遍历、创建等操作技巧,需要的朋友可以参考下
    2017-02-02
  • swagger @ApiModel添加实体类不生效的解决

    swagger @ApiModel添加实体类不生效的解决

    这篇文章主要介绍了swagger @ApiModel添加实体类不生效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教。
    2022-01-01
  • SpringBoot 签到奖励实现方案的示例代码

    SpringBoot 签到奖励实现方案的示例代码

    这篇文章主要介绍了SpringBoot 签到奖励实现方案的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Java中MapStruct映射处理器报错的问题解决

    Java中MapStruct映射处理器报错的问题解决

    MapStruct是一个强大的Java映射框架,它能够在编译时生成映射代码,,本文主要介绍了Java中MapStruct映射处理器报错的问题解决,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • idea构建web项目的超级详细教程

    idea构建web项目的超级详细教程

    好多朋友在使用IDEA创建项目时,总会碰到一些小问题,下面这篇文章主要给大家介绍了关于idea构建web项目的超级详细教程,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • Java实现HTML转PDF及合并PDF文件详细教程

    Java实现HTML转PDF及合并PDF文件详细教程

    之前在工作中遇到过一个需求,是将用户填写的申报,由固定模板的来生成pdf,后来想到先把内容生成html,然后再把html格式的内容转换成pdf,这篇文章主要介绍了Java实现HTML转PDF及合并PDF文件的相关资料,需要的朋友可以参考下
    2025-07-07
  • Java Stream流从入门到精通

    Java Stream流从入门到精通

    Stream(流)是Java 8引入的一个重要特性,它提供了一种声明式的数据处理方式,本文给大家介绍Java Stream流从入门到精通,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • SpringBoot集成单点登录CAS的方法实现

    SpringBoot集成单点登录CAS的方法实现

    本文主要介绍了SpringBoot集成单点登录CAS的方法实现,包括CAS的基本概念、集成步骤、具体代码示例等,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-03-03

最新评论