JAVA应用频繁GC问题排查过程

 更新时间:2026年04月01日 14:45:06   作者:希望你可以把爱留在南京  
本文主要记一次针对系统频繁GC问题的排查过程,通过分析dump堆栈文件和线程转储,发现慢接口的代码中存在慢SQL,导致数据库连接池耗尽,进而阻塞Dubbo线程,引发频繁GC,解决方案包括慢SQL优化、方法优化和业务优化

频繁GC背景

处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及Full GC次数过多的问题。当然,这些问题的最终导致的直观现象就是系统运行缓慢,并且有大量的报警。

本文主要记一次针对系统频繁GC这一问题,提供该问题的排查思路,从而定位出问题的代码点,进而提供解决该问题的思路。

不再重复赘述网上大部分排查GC命令,工具使用或者GC本身定义等

问题描述

发现商品应用product-dubbo频繁GC告警

规则名称: 【性能告警】应用GC次数大于20次/分钟(且新生代GC时间大于50ms)
触发时值: 74
监控指标: [AlarmName=GC次数 application=product-dubbo ...]
持续时长: 0s
触发时间: 2025-06-21 11:44:06

同时有慢接口告警

规则名称: 【严重性能告警】应用接口平均响应时间大于1s
触发时值: 2.4098
规则备注: 过去十分钟内的平均响应时间
监控指标: [AlarmName=接口RT application=product-client uri=/api/product/client/list]
持续时长: 0s
触发时间: 2025-06-21 11:03:39

问题排查思路

对于线上系统突然出现频繁GC问题,这种情况可能的原因主要有:代码中某个位置读取数据量较大,导致系统内存耗尽,从而导致Full GC次数过多,那么首先需要做的就是,导出dump堆栈文件,分析其具体的内存信息

使用线程转储(Thread Dump)分析工具:

链接: link

其中等待线程数558,超时等待线程数49,运行线程数44

未发现消耗CPU的线程和阻塞线程

同时也没有死锁线程

排除掉异常线程导致频繁gc问题

进一步分析线程池里包含的线程

其中dubbo线程占据90%,其余线程比如tomcat线程,logback线程,自定义线程池线程等只占一小部分

排查dubbo线程堆栈发现问题

出现mysql存在异常

同时存在druid超时线程

综合分析

dubbo线程调用方法里面出现mysql异常,结合告警的慢接口是同一处,怀疑是否是慢sql导致的数据库连接池druid打满,进而导致dubbo大部分线程处于等待状态

通过arthas分析本次告警的慢接口

trace com.biz.prooduct queryList '#cost > 100'

进一步验证上述分析结论

通过arthas分析内存对象

dumpheap --live /tmp/dump.hprof'

打开本地jvm分析工具分析hprof文件如下:

发现堆中占内存前三位的分别是char[]、String 和 ConcurrentHashMap$Node三个类其中char[]占用绝大部分空间,进一步分析char[]数据:

上述char[]中存放的基本都是/api/product/client/list返回的数据

综合分析

由于/api/product/client/list是客户端获取商品列表接口,客户端每次查询商品都会去掉用,存在大量并发的场景,并且接口方法内部是拉取全量商品数据。

同时该接口有数次慢sql的代码,慢SQL进一步导致数据库连接池耗尽,进而阻塞Dubbo线程的典型故障链,从而引发频繁GC。

解决方案

1.慢sql优化(通过执行计划按量优化索引等)

2.方法优化(异步处理非核心代码)

3.业务优化(监听商品变动方法,客户端拉取全量商品存在本地,商品发生变动通知客户端重新拉取商品)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • idea ssm项目java程序使用十六进制rxtx包向串口发送指令的方法

    idea ssm项目java程序使用十六进制rxtx包向串口发送指令的方法

    这篇文章主要介绍了idea ssm项目java程序向串口发送指令并且使用十六进制 rxtx包,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • java8中Stream的使用示例教程

    java8中Stream的使用示例教程

    Stream是Java8的一大亮点,是对容器对象功能的增强,下面这篇文章主要给大家介绍了关于java8中Stream使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-10-10
  • Java设计模式之状态模式详解

    Java设计模式之状态模式详解

    Java 中的状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态发生改变时改变其行为,本文将详细介绍 Java 中的状态模式,我们将从状态模式的概述、结构与实现、优缺点、适用场景等方面进行讲解,需要的朋友可以参考下
    2023-05-05
  • Spring 静态变量/构造函数注入失败的解决方案

    Spring 静态变量/构造函数注入失败的解决方案

    我们经常会遇到一下问题:Spring对静态变量的注入为空、在构造函数中使用Spring容器中的Bean对象,得到的结果为空。不要担心,本文将为大家介绍如何解决这些问题,跟随小编来看看吧
    2021-11-11
  • Java单例模式实例简述

    Java单例模式实例简述

    这篇文章主要介绍了Java单例模式,在Java应用程序设计中有着非常重要的作用,本文以实例形式对此加以简单分析,需要的朋友可以参考下
    2014-09-09
  • java反射之方法反射的基本操作方法

    java反射之方法反射的基本操作方法

    下面小编就为大家带来一篇java反射之方法反射的基本操作方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • MybatisPlus多表连接查询的具体实现

    MybatisPlus多表连接查询的具体实现

    MyBatis Plus是一款针对MyBatis框架的增强工具, 它提供了很多方便的方法来实现多表联查,本文主要介绍了MybatisPlus多表连接查询的具体实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • SpringBoot中配置文件pom.xml的使用详解

    SpringBoot中配置文件pom.xml的使用详解

    SpringBoot的pom.xml文件是Maven项目的核心配置文件,用于定义项目的依赖、插件、构建配置等信息,下面小编就来和大家详细介绍一下它的具体使用吧
    2025-03-03
  • Java字符串格式化功能 String.format用法详解

    Java字符串格式化功能 String.format用法详解

    String类的format()方法用于创建格式化的字符串以及连接多个字符串对象,熟悉C语言的同学应该记得C语言的sprintf()方法,两者有类似之处,format()方法有两种重载形式
    2024-09-09
  • Spring-webflux访问关系型数据库实战

    Spring-webflux访问关系型数据库实战

    这篇文章主要为大家介绍了Spring-webflux访问关系型数据库实战详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07

最新评论