记一次生产环境排查OOM问题,byte[]数组超多
背景
服务部署在内网,单机springboot,我们最近发版比较频繁,基本上每天都会重启应用,最近突然发现会出现OOM问题
排查思路
- 首先启动脚本一定得加启动参数,不然什么信息也没有,如果之前没加,那就只能加上后,等下次OOM再排查了
-XX:+HeapDumpOnOutOfMemoryError 设置当首次遭遇内存溢出时导出此时堆中相关信息
-XX:HeapDumpPath=/tmp/heapdump.hprof 指定导出堆信息时的路径或文件名
- 把dump文件下载下来,看一下文件的大小和启动参数-Xmx 设置的大小是否差不多,如果dump文件明显小的话先查下其他方向,比如是否在启动时设置了元空间大小(-XX:MaxMetaspaceSize)或者堆外内存大小之类的参数,简而言之就是dump文件如果明显小于设置的堆内存,可能就需要考虑不是堆内存溢出的情况
- 找个64位的jdk,打开bin目录下的jvisualvm.exe(openJDK貌似没有),可以下zulu家的或者oracle的
- 加载dump文件,记得选到*.hprof
- 首先点到类这边,看下哪些对象特别多,有时候可以直观的看出问题,但我这边是byte[]特别多,此时猜测是否是有内存泄漏
- 尝试从byte[]的内容用new String[]转字符串,发现是乱码,所以猜测数据内容应当不是字符串了,也更像内存泄漏了
- 点回概要,查找最大的20个对象,这边加载要一会,出来后从第一个查起,一般第一个就是嫌疑最大的
- 在引用处查找最近的gc根节点,说实话看不太懂这个意思,但是就是这样查的
- 对结果再使用在线程中显示功能
- 此处打码的地方是我们项目前人自己实现的mybatis分页功能,去看一下此处的代码
- 红框框起的两个地方,都是实现了AutoCloseable方法的,但是却没有调用对象的close()方法
- 可以确定问题就在此处了,随着项目体量增大,分页查询越来越多,未关闭的流也越来越多,内存泄漏越来越严重直至项目才运行两三小时就出现OOM
13.修复也很简单,把流用完关了就完事了
总结
这种系统级别的框架,要么用第三方的,要么就让大佬去写,让半吊子写真的是埋坑,当然也和我所在的是一个垃圾外包团队有点关系,解决了就好了,继续混着。