堆内存溢出排查案例

174 阅读2分钟

报错信息

java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Java heap space                                                                                                   

很奇怪,理论上堆内存溢出后,服务会挂,但我的服务没有挂掉,仍然可以访问

1、下载服务内存快照

方式比较多:

  • 可以使用各个OS的命令行+进程id处理
  • 可以使用arthas处理

2、分析内存占用情况

可以使用eclispe出品的mat工具(推荐),也可以使用idea自带的内存分析工具,右键选择idea打开即可

MAT: image.png IDEA:

参考链接:www.jetbrains.com/help/idea/c…

image.png 一般来讲崩溃的容易分析,这种不崩溃的就不太容易分析,而且抓不到具体报错点的内存快照,建议抓取报错执行点前(越近越好),侧面反应当时的内存情况。

3、 业务

用户上传大量不同类型的文件ID,本服务获取到文件ID后,获取到流(异步),根据流生成临时文件(异步),转换文件为图片(异步),批量上传所有图片,返回图片ID

这里面的内存一边使用,一边清理,一边删除临时文件。由于异步,内存无法计算,加上线程中的数据初始化,一般会翻倍内存

4、服务启动后基本在1个G内存占用,服务器启动给了1024最大,频繁溢出

解决: 1、 逻辑没问题,直接调大内存解决 2、 逻辑存在大对象的生成或者死循环创建对象,那就改逻辑 3、 必要的还是要优化原有逻辑,注意对对象的创建尽量少,注意如果存在重复尽量减少重复的内存占用。尽可能少的使用内存,降低问题出现。 4、 代码报错是有具体位置,最终只是大概推断出,在转换数据的环节新建对象的时候超出堆大小,还是没排查到具体的问题。暂时调整了堆大小解决,后续优化业务。