记一次OOM异常解决
问题描述
一台服务器出现OOM(为本应用分配了4G内存),挂掉了
java.lang.OutOfMemoryError: GC overhead limit exceeded
问题排查
拿到dump文件,使用jvisualvm打开查看后,发现下面两个对象实例数,占用空间过高
类名 | 实例数百分比 | 实例数 | 大小 |
---|---|---|---|
org.apache.xmlbeans.impl.store.Xobj$AttrXobj | 40% | 1500w | 2G |
org.apache.xmlbeans.impl.store.Xobj$ElementXobj | 12% | 450w | 700M |
问题分析
查代码发现疑似是使用poi解析excel文件时解析文件占用过多内存,解析文件的时候会解析整个文件,解析excel其实就是在解析xml,非常的消耗内存
问题解决
调查发现可以使用流式读取一次只读取特定的行数,降低内存占用
测试验证,未修改前,设置jvm内存为500M,解析1M以上的excel文件就会报OOM,修改后,问题未出现
解决方案
使用这位仁兄写成的包装库,因为不想升级项目poi的版本,影响太大,同时又想用到原来的Workbook里面的一些api,所以选择了1.0.2版本,这版的poi依赖版本依然高于我们项目中的poi,于是只好把fork一份之后降低poi版本后重新编译一个包出来用
reference
Updated: 2023-07-08 20:33
Created: 2023-06-04 20:00