记录一次线上OOM问题排查处理过程

文章描述了一种针对Docker部署的Springboot单体项目内存溢出问题的排查流程。通过dockerlogs获取日志,使用MemoryAnalyzer(MAT)工具分析内存dump文件,关注Histogram、dominator_tree和thread_overview来定位问题。建议调整JVM堆内存参数并及时生成dump文件以辅助诊断。

背景

项目为docker部署的springboot单体项目(非前后端分离),前端文件是集成在项目的类路径的resources路径下的。项目使用ruoyi-vue版本做为开发原始代码。
系统目前没什么用,主要是客户分公司在基础数据模块录入数据比较多,目前系统数据记录条数在122W+。

现象

系统运行一段时间,就会出现以下报错,且系统是不可用的状态:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

排查过程

  1. 使用命令docker logs -f 容器名称/容器Id,查看日志发现关键提示信息:
    在这里插入图片描述
    也就是Java堆内存溢出

2. 接下来一顿度娘,发现可以使用Memory Analyzer做分析,于是到官网下一波: https://www.eclipse.org/mat/downloads.php
选择中国镜像源

在这里插入图片描述
在这里插入图片描述
3. 接下来是将线上的程序,分配一定的JVM初始及最大堆内存大小运行:

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home

参数说明

-Xms 初始堆内存大小
-Xmx 最大堆内存大小
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath 表示在出现堆内存溢出时,在哪个目录生成dump文件,这里指定了容器内部的home目录,且此必须存在

在这里插入图片描述

  1. 接下来使用MAT工具打开文件后,依次查看下图标红的地方,对代码进行分析
  • 占用内存过大的对象有哪些(Histogram)
  • 被谁引用(dominator_tree)
  • 定位到具体的代码(thread_overview)

在这里插入图片描述

  1. 如果担心dump文件大,占用磁盘空间,可以再你排查的时候,再进行生成。
    可以执行以下命令生成:

在这里插入图片描述
在这里插入图片描述
以上就是自己总结的内存溢出排查方法,大家可以参考,欢迎大佬指正!!

### Java 线OOM OutOfMemoryError 解决方案 #### 一、理解 OOM 错误类型 Java 应用程序中的 `OutOfMemoryError` 主要分为几种常见类型: - **Java 堆内存不足(Java Heap Space OOM)** 这种类型的错误表明 JVM 的堆空间不足以完成垃圾回收操作,通常是因为对象过多或单个对象过大。当应用程序创建大量临时对象而未能及时释放时,可能会触发此类错误[^1]。 - **GC Overhead Limit Exceeded** 此错误表示垃圾收集器花费了太多时间尝试清理少量可用内存,导致应用性能严重下降甚至停止响应。Oracle 官方指出该情况通常是由于频繁的小规模垃圾回收造成系统资源耗尽所致[^2]。 #### 二、诊断工具与技术 为了有效定位和解决问题,在线环境下的调试至关重要。可以采用如下手段来捕获必要的信息用于后续分析: - 使用 `-XX:+HeapDumpOnOutOfMemoryError` 参数配置JVM启动参数,使得发生OOM时自动生成heap dump文件供离线分析。 - 利用 VisualVM 或 JProfiler 进行实时监控,观察内存变化趋势以及各代存活对象数量;还可以通过这些工具获取线程转储(Thread Dump),帮助识别是否存在死锁等问题影响正常工作流程。 - 查看日志记录,特别是那些由第三方库生成的日志条目,它们可能隐藏着关于异常行为的重要线索。 ```bash jmap -histo:live <pid> | head -n 50 # 显示当前进程中前五十大类实例占用的总字节数量 ``` 上述命令可以帮助快速了解哪些类正在消耗较多的内存资源。 #### 三、具体措施建议 针对不同种类的 OOM 错误采取相应的预防性和修复性行动: 对于 **Java Heap Space OOM**: - 分析 heap dump 文件找出泄露源码位置; - 减少不必要的缓存数据保留期限; - 提高数据库查询效率减少一次性加载的数据集大小; - 合理调整最大堆尺寸(`-Xmx`) 和初始堆尺寸 (`-Xms`) 设置以适应实际负载需求。 面对 **GC Overhead Limit Exceeded** : - 修改 GC算法选项如选用G1收集器替代CMS; - 扩展年轻代比例使更多短生命周期的对象能够在此处被迅速清除而不进入老年代引发全局扫描; - 如果业务逻辑允许的话适当放宽gc开销阈值(-XX:GCTimeRatio=99); - 对于某些特殊场景考虑引入软/弱引用机制代替强引用来管理可选组件间的依赖关系从而降低整体压力. ```xml <property name="spring.datasource.hikari.maximumPoolSize" value="${MAX_POOL_SIZE}" /> <!-- 配置连接池的最大活跃数 --> ``` 合理设置数据库连接池参数也是缓解内存紧张的有效途径之一。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值