自己挖的坑自己填--jxl进行Excel下载堆内存溢出问题
今天在进行使用 jxl 进行 Excel 下载时,由于数据量大(4万多条接近5万条数据的下载),数据结构过于负责,存在大量大对象(虽然在对象每次用完都设置为null,但还是存在内存溢出问题),加上本地电脑内存不大(只有8G),导致下载数据时报堆内存溢出,下载失败。
Exception data: java.lang.OutOfMemoryError
at jxl.write.biff.MemoryDataOutput.write(MemoryDataOutput.java:72)
at jxl.write.biff.File.write(File.java:149)
at jxl.write.biff.RowRecord.writeCells(RowRecord.java:324)
at jxl.write.biff.SheetWriter.write(SheetWriter.java:479)
at jxl.write.biff.WritableSheetImpl.write(WritableSheetImpl.java:1431)
at jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:915)
下面是案例复现的简单模拟代码:
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId >
<artifactId>jxl</artifactId >
<version>2.6.12</version >
</dependency >
public class MyExcel {
public static void main(String[] args) throws Exception {
File xlsFile = new File("E:\\jxl.xls");
// 创建一个工作簿
WritableWorkbook workbook = Workbook.createWorkbook(xlsFile);
// 创建一个工作表
WritableSheet sheet = workbook.createSheet("sheet1", 0);
Map<Integer, ArrayList<Map<Integer, Person>>> mapListMap = new HashMap<>();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBatisConfig.class);
PersonServiceImpl bean = context.getBean(PersonServiceImpl.class);
//获取数据库数据
List<Person> listBean = bean.getList();
//进行数据处理
for (int row = 0; row < 45000; row++) {
ArrayList<Map<Integer, Person>> listMap = new ArrayList<Map<Integer, Person>>();
for (int col = 0; col < 30; col++) {
Map<Integer, Person> map = new HashMap<Integer, Person>();
for (int j = 0; j < listBean.size(); j++) {
map.put(j, listBean.get(j));
}
listMap.add(map);
map = null;
}
mapListMap.put(row, listMap);
listMap = null;
}
//写数据
for (int row = 0; row < 45000; row++) {
ArrayList<Map<Integer, Person>> listMap = mapListMap.get(row);
for (int col = 0; col < 30; col++) {
Map<Integer, Person> map = listMap.get(col);
for (int j = 0; j < listBean.size(); j++) {
Person person = map.get(j);
sheet.addCell(new Label(col, row, person.getId()+"" + row + col));
sheet.addCell(new Label(col, row, person.getName() + row + col));
sheet.addCell(new Label(col, row, person.getAge()+"" + row + col));
map = null;
}
}
listMap = null;
}
workbook.write();
workbook.close();
}
运行后结果:
解决办法:
(1)最简单的方法是加大内存,本地电脑内存过小,当把代码部署到公司测试环境(测试环境内存是16G)时该问题不再复现;
(2)采用临时文件写入EXCEL功能,设定临时文件的位置,可以有效的避免内存溢出(jxl版本必须是2.6.12及其以上,2.6版本没有采用临时文件的功能);
public static void main(String[] args) throws Exception {
File xlsFile = new File("E:\\jxl.xls");
// 创建一个工作簿
WorkbookSettings ws = new WorkbookSettings();
ws.setUseTemporaryFileDuringWrite(true);
ws.setTemporaryFileDuringWriteDirectory(new File("E:\\"));//指定一个临时文件路径
WritableWorkbook workbook = Workbook.createWorkbook(xlsFile,ws);
// 创建一个工作表
WritableSheet sheet = workbook.createSheet("sheet1", 0);
Map<Integer, ArrayList<Map<Integer, Person>>> mapListMap = new HashMap<>();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBatisConfig.class);
PersonServiceImpl bean = context.getBean(PersonServiceImpl.class);
//获取数据库数据
List<Person> listBean = bean.getList();
//进行数据处理
for (int row = 0; row < 45000; row++) {
ArrayList<Map<Integer, Person>> listMap = new ArrayList<Map<Integer, Person>>();
for (int col = 0; col < 30; col++) {
Map<Integer, Person> map = new HashMap<Integer, Person>();
for (int j = 0; j < listBean.size(); j++) {
map.put(j, listBean.get(j));
}
listMap.add(map);
map = null;
}
mapListMap.put(row, listMap);
listMap = null;
}
//写数据
for (int row = 0; row < 45000; row++) {
ArrayList<Map<Integer, Person>> listMap = mapListMap.get(row);
for (int col = 0; col < 30; col++) {
Map<Integer, Person> map = listMap.get(col);
for (int j = 0; j < listBean.size(); j++) {
Person person = map.get(j);
sheet.addCell(new Label(col, row, person.getId()+"" + row + col));
sheet.addCell(new Label(col, row, person.getName() + row + col));
sheet.addCell(new Label(col, row, person.getAge()+"" + row + col));
}
map = null;
}
listMap = null;
}
workbook.write();
workbook.close();
}
当开始执行下载时,会产生一个临时文件,jxl 会把数据写入到这个临时文件中,写入结束后会把这个临时文件删除:
PS:
(1)Excel 表一个 sheet 页可以存储6万条,所以一般超过5万条的,其他的数据就存储其他sheet中;或采用分成几个 Excel 表来实现数据下载;
(2)今天测试下载的 Excel 数据文本有170M(数据有4.8w条),通过MS Office 打开失败,为空 Excel 表,但通过 WPS 可以正常打开。
自己挖的坑自己填--jxl进行Excel下载堆内存溢出问题的更多相关文章
- Redis采坑(一)——数据无法插入,内存溢出
一.采坑背景 在最大数据分析的过程中,redis是被当做热数据的缓存库使用的,在某一天中,redis数据库热数据无法插入,此时数据量大概在100万左右,很是纠结,为什么不能插入?程序的错误,不可能,没 ...
- 自己挖的坑自己填--JVM报内存溢出
在写定时任务时,对表数据进行批量操作,测试数据有10万条左右,在测试时发现跑着跑着出现内存溢出现象,最后发现创建的对象paramList 和tmBeanList没有被回收,经过资料查找,发现是循环内不 ...
- 自己挖的坑自己填--docker创建实例出现Waiting for SSH to be available…
在之前使用Docker for Windows Installer.exe直接安装,通过docker-machine-driver-vmwareworkstation.exe实现docker和VM的共 ...
- 自己挖的坑自己填-- maven打jar包部署服务器报错
1.今天 mvn install 后把 jar 包部署到服务器上,执行 java -jar xx.jar 报 "no main manifest attribute,in xx.jar&qu ...
- 自己挖的坑自己填--Mybatis mapper文件if标签中number类型及String类型的坑
1.现象描述 (1)使用 Mybatis 在进行数据更新时,大部分时候update语句都需要通过动态SQL进行拼接.在其中,if标签中经常会有 xxx !='' 这种判断,若 number 类型的字段 ...
- 挖个坑,写一个Spring+SpringMVC+Mybatis的项目
想挖个坑督促自己练技术,有时候想到一个项目,大概想了一些要实现的功能,怎么实现.现在觉得自己差不多能完成QQ空间的主要功能了.准备立个牌坊,写一个类似功能的网站.并且把进度放到这里来. 初步计划实现以 ...
- JAVAFX之tableview界面实时刷新导致的内存溢出(自己挖的坑,爬着也要出来啊0.0)
这几天遇到了一个问题,不幸开发的一个cs架构的工具,客户端开启后,内存一直在缓慢增长最终导致进程卡死,花了4天时间,终于爬出来了... 客户端通过timer定时器每30秒查询一次数据库以及一些业务逻辑 ...
- jxl导出Excel中需要跳过的的坑
正如上篇文章(JXL封装不能使用static关键字问题)所说,在jxl导出Excel时候如果频繁使用到WritableCellFormat去设置单元格的样式,这个时候经常会出现两种情况: 1.报警告: ...
- java利用jxl操作Excel
/** * 把从数据库查询到的数据,写入电子表格 * * @throws Exception */ public void createXls() throws Exception { Dao dao ...
随机推荐
- Javascript 严格模式("use strict";)详细解解
1 1 1 Javascript 严格模式("use strict";)详细解解 "use strict";定义JavaScript代码应该在"str ...
- Error: Cannot find module 'koa-router'
Error: Cannot find module 'koa-router' koa-router !== koa-route # install OK $ yarn add koa-router h ...
- 增强 CT & CT & MR
增强 CT & CT & MR CTA,增强 CT Computed Tomography (CT) CT 计算机断层扫描 Computed Tomography (CT) Angio ...
- 为什么说USDN是一种应用型稳定币?
USDN是由NGK Global出品的一种新型稳定币系统,里面是涵盖了包括货币供需.Bancor.抵押借贷等在内的一整套算法.该稳定币构想一经提出,便在社区引发了不小的热度. 官方对于USDN的定位是 ...
- java初学者必看之构造方法详细解读
java初学者必看之构造方法详细解读 构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法. 格式 public 类名称(参数类型 参数名称){ 方法体 } 注 ...
- spring5学习笔记
Spring5 框架概述 1.Spring 是轻量级的开源的 JavaEE 框架 2.Spring 可以解决企业应用开发的复杂性 3.Spring 有两个核心部分:IOC 和 Aop (1)IOC:控 ...
- 【HTB靶场系列】靶机Carrier的渗透测试
出品|MS08067实验室(www.ms08067.com) 本文作者:大方子(Ms08067实验室核心成员) Hack The Box是一个CTF挑战靶机平台,在线渗透测试平台.它能帮助你提升渗透测 ...
- ElasticSearch URI 查询
公号:码农充电站pro 主页:https://codeshellme.github.io 1,URI 查询格式 URI 查询的一般格式如下: GET /index_name/_search?q=key ...
- Vue学习笔记-vue-element-admin 按装报错再按装
一 使用环境 开发系统: windows 后端IDE: PyCharm 前端IDE: VSCode 数据库: msyql,navicat 编程语言: python3.7 (Windows x86- ...
- Django Admin 在内联中覆盖保存方法(admin.TabularInline)
一 使用环境 开发系统: windows IDE: pycharm 数据库: msyql,navicat 编程语言: python3.7 (Windows x86-64 executable in ...