Hi, I’m Shendi
记一次Java内存溢出导致程序宕机的问题及排查
问题场景
今天在使用工具中的 word 转 pdf 出了问题,报502错误,打开服务器发现服务被关闭了,起初以为是误关,打开后重新转换又出现了这个问题,在项目文件夹下多了几个文件,打开才知道是因为内存溢出导致程序宕机了。
对于这个问题,起初以为是上传文件导致的内存溢出,因为我服务器上内存只剩下几百兆了,而上传的文件近30MB,于是决定在本地测试一下,通过测试得知是转换部分的问题。
排查
对于我的这种情况还是比较好排查的,因为是我自己操作发现的。已经定位到了是哪个具体的接口出了问题
于是只需要在本地进行测试就可以了,通过代码检查内存
对于代码获取内存信息,需要用到 Runtime 的三个函数
- totalMemory() - 当前占用的内存大小
- freeMemory() - 未使用的内存大小(占用但还没有使用)
- maxMemory() - 最大内存大小
通过打印输出,查看内存变化,定位问题的具体代码。
System.out.println("最大可用内存:" + Runtime.getRuntime().maxMemory());
System.out.println("当前内存:" + Runtime.getRuntime().totalMemory() + ", 未用内存: " + Runtime.getRuntime().freeMemory());
我在接口的开始,结束处,以及可能对内存有较大影响的地方都增加打印,因为接口开始即文件上传完成,所以最大的可能性是在转换的地方。
输出如下
// 接口开始 2020MB
最大可用内存:2118123520
// 49MB,31MB
当前内存:51380224, 未用内存: 33082008
// 转换前 --这里创建了输入输出流,以及拿到接口文件的数据 MultipartFile.getBytes()
// 117MB,68MB
当前内存:122683392, 未用内存: 71812848
// 转换后
// 2020MB,656MB
当前内存:2118123520, 未用内存: 688338112
由上面的数据可以分析出来,问题就是出在了转换上,转换将内存吃满了,这还是我本地调试。
以及在转换前,MultipartFile.getBytes() 拿到文件数据并通过这个数据创建输入流的操作也吃了一大内存,文件只是近30MB。还有很大的优化空间
END