原创 |我是如何解决POI解析Excel出现的OOM问题的?
程序员文章站
2022-06-22 09:47:08
背景 之前接手过一个解析Excel的项目,使用的是Java里的POI组件解析的,但是在解析时候经常出现OOM,后来我从下面几个方面优化了下,解决了99%的问题,对,你没看错,只解决了99%。 解决方案 1.调整JVM的堆内存 我们知道几乎所有的java对象实例都存放在Java堆中,出现OOM肯定是堆 ......
背景
之前接手过一个解析excel的项目,使用的是java里的poi组件解析的,但是在解析时候经常出现oom,后来我从下面几个方面优化了下,解决了99%的问题,对,你没看错,只解决了99%。
解决方案
1.调整jvm的堆内存
我们知道几乎所有的java对象实例都存放在java堆中,出现oom肯定是堆内存不够用了,所有先调大堆内存。
下面命令把jvm启动后堆的初始内存和最大内存调整为4g:
java -xms4g -xmx4g
2.限制excel大小
数据多占用内存就大,在观察了一段时间后发现有的excel是有图片或者有几十个sheet页,而真正需要解析的数据可能就几百行,所以直接在上传时候限制了excel文件的大小。
3.修改poi源码
上面两个方案后虽然出现oom的频率低了,但是还是会有,后来找了几个报oom的excel跟踪poi源码,发现好多空行poi都创建了对象,直接修改成 空行不处理就好了。
项目中使用的poi版本是3.17,修改的是xssfsheet.java的initrows()方法,改后的代码如下,其实只加了三行代码(包含大括号):
private void initrows(ctworksheet worksheetparam) { _rows.clear(); tables = new treemap<string, xssftable>(); sharedformulas = new hashmap<integer, ctcellformula>(); arrayformulas = new arraylist<cellrangeaddress>(); for (ctrow row : worksheetparam.getsheetdata().getrowarray()) { //修改poi源码 begin if(row.getcarray().length<=0){ continue; } //修改poi源码 end xssfrow r = new xssfrow(row, this); // performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory final integer rownumi = new integer(r.getrownum()); // nosonar _rows.put(rownumi, r); } }
上面三个方案如果还不行,可以考虑使用 easyexcel,alibaba开源的,基于注解,可读性好,想了解更多可以参考:
推荐阅读
1.手把手带你用数据库中间件mycat+springboot完成分库分表
2.盘点 35 个 java 代码优化细节
3.阿里面试官:分别说说微信和淘宝扫码登录背后的实现原理?
4.一分钟带你了解下mybatis的动态sql!
5.一分钟带你了解下spring security!
如果觉得文章不错,希望可以随手转发或者”在看“哦,非常感谢哈!
关注下方公众号后回复「1024」,有惊喜哦!
下一篇: java 文件下载