原創 |我是如何解決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」,有驚喜哦!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM