解决Java POI导出大数据量Excel报错:java.lang.OutOfMemoryError: Java heap space

问题背景:

有业务需要进行数据导出的操作,在进行导出任务超过15万行的数据导出时,出现了问题:

java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: GC overhead limit exceeded

关于为何会报错此信息:
在JVM中假如98%的时间是用于GC且可用的 Heap size 不足2%的时候将抛出此异常信息。

问题分析:

代码如下:

XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("书目导出");
/**
	省略获取数据并向sheet页中写入的逻辑
*/
FileOutputStream fileOutputStream = new FileOutputStream(file);
//下面这行报的错
workbook.write(fileOutputStream);

fileOutputStream.close();

报错代码:workbook.write(fileOutputStream);这一行代码导致报错,初步定义问题时由于XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx,在写入数据量超出65536条后就会报异常。

解决方案:

POI 3.8版本开始,提供了一种基于XSSF的低内存占用的API,SXSSFWorkbook。
流媒体版本的XSSFWorkbook实现“BigGridDemo”策略。允许写入非常大的文件,而不会耗尽内存一个可配置的行部分在任何时间保存在内存中。

官方介绍:

SXSSF(软件包:org.apache.poi.xssf.streaming)是XSSF的API兼容流扩展,用于必须生成非常大的电子表格并且堆空间有限时使用。SXSSF 通过限制对滑动窗口中的行的访问来实现其低内存占用量,而 XSSF 则允许访问文档中的所有行。不再位于窗口中的旧行将变得不可访问,因为它们将写入磁盘。

滑动窗口:

一个窗口为 100 行的工作表。当行计数达到 101 时,rownum=0 的行被刷新到磁盘并从内存中删除,当 rownum 达到 102 时,rownum=1 的行被刷新,依此类推。

SXSSFWorkbook 如何降低内存

SXSSFWorkbook 默认使用内联字符串而不是共享字符串表。这是非常有效的,因为不需要将文档内容保存在内存中,但众所周知,这些文档会生成与某些客户端不兼容的文档。启用共享字符串后,文档中的所有唯一字符串都必须保存在内存中。根据您的文档内容,这可能比禁用共享字符串使用更多的资源。

压缩临时文件

SXSSF 在临时文件(每个工作表一个临时文件)中刷新工作表数据,并且这些临时文件的大小可能会增长到非常大的值。例如,对于 20 MB 的 csv 数据,临时 xml 的大小将超过 1 GB。如果临时文件的大小有问题,您可以告诉 SXSSF 使用 gzip 压缩:

SXSSFWorkbook wb = new SXSSFWorkbook();
wb.setCompressTempFiles(true);//临时文件将被压缩

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐州蔡徐坤

又要到饭了兄弟们

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值