背景
之前接手過一個解析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」,有驚喜哦!