记一次内存泄漏导致的线上超时问题

server/2025/2/27 15:04:12/

最近新上线功能使用了线程池来优化异步处理消息,对于CPU的使用率有所升高,自从新版本上线后,发现运行每隔几天就会出现超时的问题,经过排查发现是内存泄漏频繁YGC导致的,记录下本次排查的一些思路。

问题排查过程

定位问题线程 VM Thread

出现超时问题,首先查看CPU使用率,发现CPU使用率飙升到平时的5倍多;

CPU使用率 200%+,1min 负载在6左右,由于机器是4核的,按理说CPU还有余量。

# 查看CPU使用率和负载的情况,java进程PID = 1
top

还是查看CPU使用率最高的线程,为何异常占用CPU资源

# 查看线程的CPU使用率
top -Hp 1

结果显示 PID=74 这个线程占CPU较高且持续出现,

# 将PID转为16进制,结果是 0x4a
printf "%x\n"# 由于Java程序运行在 ubuntu 下,切换用户
su ubuntu
# 保存当前线程转储文件到本地
jstack 1 > thread_dump.txt# 查询 对应线程 0x4a 的运行情况,打印出其后的30条日志
less thread_dump.txt | grep -A 30 "0x4a"

输出如下所示

"VM Thread" os_prio=0 tid=0x00007f6f244c0800 nid=0x4a runnable "Gang worker#0 (Parallel GC Threads)" os_prio=0 tid=0x00007f6f24027000 nid=0x38 runnable "Gang worker#1 (Parallel GC Threads)" os_prio=0 tid=0x00007f6f24028800 nid=0x39 runnable "G1 Main Concurrent Mark GC Thread" os_prio=0 tid=0x00007f6f24042000 nid=0x3d runnable "Gang worker#0 (G1 Parallel Marking Threads)" os_prio=0 tid=0x00007f6f24044000 nid=0x3e runnable "G1 Concurrent Refinement Thread#0" os_prio=0 tid=0x00007f6f2402e800 nid=0x3c runnable "G1 Concurrent Refinement Thread#1" os_prio=0 tid=0x00007f6f2402d000 nid=0x3b runnable "G1 Concurrent Refinement Thread#2" os_prio=0 tid=0x00007f6f2402b000 nid=0x3a runnable "VM Periodic Task Thread" os_prio=0 tid=0x00007f6f2450c000 nid=0x63 waiting on condition JNI global references: 529

即 VM Thread 这个线程占据了较多CPU资源。 什么是VM Thread 呢?

VM Thread 是 JVM 内部的一个核心线程,负责执行需要 全局安全点(Safepoint) 的操作。主要负责:

  1. 协调安全点
    1. 当 JVM 需要执行某些关键操作(如垃圾回收、代码反优化、线程栈dump)时,必须确保所有应用线程都进入安全点(即线程暂停在已知的安全位置,不会修改堆内存)。
    2. VM Thread 负责 触发安全点 并等待所有应用线程到达安全点,再执行后续操作。
  2. 处理 JVM 内部操作:如偏向锁撤销、线程挂起/恢复等;
MAT分析是否存在内存泄漏

VM Thread 不是 CPU 飙升的主因,但 G1回收期 的 GC 线程和 GC 行为(如频繁 Young GC、并发标记、Full GC)可能导致 CPU 高负载,因此分析堆内存使用情况。使用 jstat命令可以查看堆内存各部分的使用量

# 间隔2s输出堆内存使用情况
jstat -gc 1 2s输出列含义:
S0C, S1C: Survivor 0和1的容量(Capacity)
S0U, S1U: Survivor 0和1已使用(Used)
EC: Eden区容量
EU: Eden区已使用
OC: 老年代容量
OU: 老年代已使用
MC: Metaspace容量
MU: Metaspace已使用
CCSC: Compressed Class Space容量
CCSU: Compressed Class Space已使用
YGC: Young GC次数
YGCT: Young GC总时间
FGC: Full GC次数
FGCT: Full GC总时间
GCT: 总GC时间

部分输出如下,可以看到

OU 近似等于 OC,可能存在老年代被填满的风险,进而触发Full GC;

FGC大于0,已出现 Full GC的情况;

Young GC的情况。YGC从18476逐渐增加到18486,每次输出间隔2秒,YGC次数增加了约10次,说明Young GC发生得非常频繁,大约每2秒就有一次Young GC。YGCT的总时间是229秒左右,每次Young GC的平均时间约12毫秒每次。

在这里插入图片描述

可以看出堆内存占用异常,发生了内存泄漏的问题,导出堆栈信息进行分析,

# PID = 1 堆栈转储
jmap -dump:format=b,file=heap.hprof 1

打开MAT工具,从MAT提供的可疑报告以及统计中可以看到, KryoConnInfo这个对象内存对象极多,远远超出了合理值,自此找到了问题在哪,进一步分析代码,发现是引用的某个sdk存在消息乱序的问题没有相应进行处理,导致消息无法被清除进而导致内存泄漏。

在这里插入图片描述

修复内存泄漏问题

最后一步,分析代码,修复问题。

若有不同见解欢迎讨论~


http://www.ppmy.cn/server/171061.html

相关文章

供应链与生产制造L1-L4级高阶流程规划框架(53页PPT)

《供应链与生产制造L1-L4级高阶流程规划框架》是一份详尽的文档,它详细描述了从战略规划到制造与供应链管理的整个流程。文档首先从1.0战略规划管理开始,涵盖了企业整体战略的制定和执行。方案还强调了流程信息化管理的重要性,指出通过信息化…

怎么合并主从分支,要注意什么

在 Git 中合并主从分支(例如将 feature 分支合并到 main 分支)是一个常见操作。以下是具体步骤和注意事项: 合并分支的步骤 切换到主分支 git checkout main确保当前在 main 分支。 拉取最新代码 git pull origin main确保 main 分支是最…

神经网络发展简史:从感知机到通用智能的进化之路

引言 神经网络作为人工智能的核心技术,其发展历程堪称一场人类对生物大脑的致敬与超越。本文将用"模型进化"的视角,梳理神经网络发展的五大关键阶段,结合具象化比喻和经典案例,为读者呈现一幅清晰的AI算法发展图谱。 一…

FPGA:UART串口接收(高干扰情况)

FPGA:UART串口接收 高干扰下UART串口接收思路UART改善串口接收模块及其思路波特率选择模块打拍延迟和边沿检测电路计数使能逻辑波特率分频计数器位计数器完成标志信号计数判断逻辑整体代码 板级验证和测试 高干扰下UART串口接收思路 在上一篇文章中介绍过UART串口接收模块&…

win11本地部署deepseek大模型(安装ollama+docker+open-webui)最终实现自己的项目可通过API调用投喂数据后的模型

硬件配置:笔记本win11,内存32G,CPU锐龙7 ,无独显;只能考虑deepseek-r1:1.5b模型。 第一步:安装Ollama 此处不过多累赘了,https://ollama.com/官网选择对应的系统版本下载即可。 需要注意的是…

RabbitMQ学习—day6—springboot整合

目录 1. springboot配置 2. 开始写RabbitMq代码 3. 队列优化 4. 插件实现延迟队列 5. 总结 前一小节我们介绍了死信队列,刚刚又介绍了 TTL,至此利用 RabbitMQ 实现延时队列的两大要素已经集齐,接下来只需要将它们进行融合,再加…

SAP Webide系列(7)- 优化FreeStyle新建项目预设模板

目录 一、背景 二、优化目标 三、定位调整点 四、调整步骤 五、效果展示 六、附言 一、背景 在每次通过Webide进行FreeStyle方式自开发SAP UI5应用的时候,新建项目,得到的模板文件都是只有很少的内容(没有路由配置、没有设置默认全屏等…

三七互娱游戏策划岗内推

【游戏策划】【美术设计】【市场推广】【游戏运营类】【技术开发】 1、协助完成战斗体验设计,包括动作、特效、镜头等; 2、负责战斗资源的需求文档撰写,对最终的战斗表现和打击感负责; 3、协助完成职业的设计与制作&#xff0c…