1.场景
从数据库查询表数据,写入excel。之前运行一直正常,突然某天报出Can not close IO 的异常报错。
2.原代码
项目使用的EasyExcel 2.2.6实现文件导出。核心代码即下图,其中data方法是根据参数条件去数据库查询数据的操作。
3.分析
(1)有的说升级EasyExcel版本,将POI版本升到3.17,经检查EasyExcel 2.2.6依赖的正是3.17。且经实验证实此问题与版本确实无关。
(2)考虑到之前一直正常,说明代码层问题不大,那问题大概率在数据量上。于是,分析代码,发现之前的代码是一次性去查询数据库数据的。这样就很容易导致堆内存溢出(Java heap space)。
4.解决方法
分页查询数据,优化代码如下:注意每次write后要清除list。
循环结束后,必须excelWriter.finish();否则并不会真正写入到excel文件中(其中实现了flash()和close IO的操作)。
附上程序跑起来后的资源使用情况:
5.反思
日常开发中,这种类似的大数据量查询场景会非常多,应从长远角度考虑到各方面因素可能导致的问题。