easyexcel 导入excel内存溢出

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20009015/article/details/89350380

之前使用的是阿里开源的easyexcel ,可以避免大部分的OOM情况,之前测试的时候也确实是,100Mexcel文件单sheet页,50多万数据 正常导入了。

但是这次有个需求,400个sheet页,10M的时候,导入出现了OOM。

报错情况:
在这里插入图片描述

然后查看测试环境jvm的参数
在这里插入图片描述

-XX:+CMSClassUnloadingEnabled -XX:CMSInitiatingOccupancyFraction=80 -XX:CMSMaxAbortablePrecleanTime=5000 -XX:+ExplicitGCInvokesConcurrent -XX:InitialHeapSize=2
09715200 -XX:MaxDirectMemorySize=419430400 -XX:MaxHeapSize=419430400 -XX:MaxNewSize=139812864 -XX:NewSize=139812864 -XX:OldPLABSize=16 -XX:OldSize=279617536 -XX:+PrintGC -XX:+Pri
ntGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:SurvivorRatio=8 -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCompressedClassPointer
s -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+UseParNewGC

将这个参数拷贝到本地的idea中的VM配置中
在这里插入图片描述

跑单元测试 成功复现
在这里插入图片描述

额外加了这个参数
-XX:+HeapDumpOnOutOfMemoryError
溢出时保存堆快照

得到一个200Mb大小的堆快照
在这里插入图片描述

使用VM工具打开分析在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

发现那个byte[] 
在这里插入图片描述
占了百分之71.4的大小

测试机器设置最大堆400MB 文件大小10MB ,解析时候溢出。调整最大堆为1G ,则正常。

在这里插入图片描述

初步分析了一下,大概是因为POI底层OPCPackage.open方法有多个重载,easyExcel中使用的是OPCPackage open(InputStream in);跟读后发现有如下代码:
byte[] buffer = new byte[4096];
int read = 0;
while( (read = inp.read(buffer)) != -1 ) {
baos.write(buffer, 0, read);
}
判断应该是由于这个问题导致OOM,修改为使用OPCPackage open(File file)或OPCPackage open(String path)可以正常解析。

附上异常信息:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3236)
at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:191)
at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource$FakeZipEntry.(ZipInputStreamZipEntrySource.java:136)
at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.(ZipInputStreamZipEntrySource.java:56)
at org.apache.poi.openxml4j.opc.ZipPackage.(ZipPackage.java:100)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:324)
at com.alibaba.excel.analysis.v07.XlsxSaxAnalyser.(XlsxSaxAnalyser.java:44)
at com.alibaba.excel.analysis.ExcelAnalyserImpl.getSaxAnalyser(ExcelAnalyserImpl.java:47)
at com.alibaba.excel.analysis.ExcelAnalyserImpl.analysis(ExcelAnalyserImpl.java:72)
at com.alibaba.excel.analysis.ExcelAnalyserImpl.analysis(ExcelAnalyserImpl.java:67)
at com.alibaba.excel.ExcelReader.read(ExcelReader.java:112)
at easyExcel.ExcelReaderTest.main(ExcelReaderTest.java:25)

在这里插入图片描述

在这里插入图片描述

解决:
easyexcel换到1.0.1版本就解决了这个问题,高版本的底层实现和低版本已经完全不一样了。
但是因为项目里面已经用了高版本的,所以降版本影响很大,因此我只是将1.0.1里面的可以解析这种大文件的代码移动到了当前版本 并重新打了一份包。

1.1.2版本在堆内存400mb的时候解析10mb的excel 堆内存溢出。 但是1.0.1版本支持,因此将1.0.1里面的部分代码和1.1.2版本进行了整合 打了新包.
新增了getbigredear方法,对原有方法不做任何改动

新增了此方法
在这里插入图片描述
https://download.csdn.net/download/qq_20009015/11128810 jar包下载

猜你喜欢

转载自blog.csdn.net/qq_20009015/article/details/89350380