zoukankan      html  css  js  c++  java
  • 原创 |我是如何解决POI解析Excel出现的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开源的,基于注解,可读性好,想了解更多可以参考:
    https://github.com/alibaba/easyexcel

    推荐阅读

    1.手把手带你用数据库中间件Mycat+SpringBoot完成分库分表
    2.盘点 35 个 Java 代码优化细节
    3.阿里面试官:分别说说微信和淘宝扫码登录背后的实现原理?
    4.一分钟带你了解下MyBatis的动态SQL!
    5.一分钟带你了解下Spring Security!


    如果觉得文章不错,希望可以随手转发或者”在看“哦,非常感谢哈!

    关注下方公众号后回复「1024」,有惊喜哦!

  • 相关阅读:
    TabControl
    Loading
    Dialog
    Combobox
    Markdown编辑器Editor.md使用方式
    XSS攻击
    跨域解决方案及实现
    angular4 自定义表单组件
    angular4 Form表单相关
    js 详解setTimeout定时器
  • 原文地址:https://www.cnblogs.com/haha12/p/12510867.html
Copyright © 2011-2022 走看看