点击关注公众号,实用技术文章及时了解

来源:blog.csdn.net/liangjf85/article/

details/84914798

在使用POI进行excel操作时,当数据量较大时经常会产生内存溢出异常。下面我们通过分析如何解决该问题

一、POI结构图

二、内存溢出问题

在项目中遇到二十万行数据要写入到excel中时会内存溢出,一般方法是调大tomcat的内存,但是调到2048M还是会内存溢出报错。因此我们分析其原因。

我们通过分析其源码,得出其实现步骤为通过InputStream一行行读取到TreeMap类型的HSSFRow结构体中,因此当数据量大时就会造成内存溢出。

public HSSFWorkbook(DirectoryNode directory, boolean preserveNodes)throws IOException{super(directory);String workbookName = getWorkbookDirEntryName(directory);this.preserveNodes = preserveNodes;// If we're not preserving nodes, don't track the//  POIFS any moreif(! preserveNodes) {clearDirectory();}_sheets = new ArrayList<HSSFSheet>(INITIAL_CAPACITY);names  = new ArrayList<HSSFName>(INITIAL_CAPACITY);// Grab the data from the workbook stream, however//  it happens to be spelled.InputStream stream = directory.createDocumentInputStream(workbookName);List<Record> records = RecordFactory.createRecords(stream);workbook = InternalWorkbook.createWorkbook(records);setPropertiesFromWorkbook(workbook);int recOffset = workbook.getNumRecords();// convert all LabelRecord records to LabelSSTRecordconvertLabelRecords(records, recOffset);RecordStream rs = new RecordStream(records, recOffset);while (rs.hasNext()) {try {InternalSheet sheet = InternalSheet.createSheet(rs);_sheets.add(new HSSFSheet(this, sheet));} catch (UnsupportedBOFType eb) {// Hopefully there's a supported one after this!log.log(POILogger.WARN, "Unsupported BOF found of type " + eb.getType());}}for (int i = 0 ; i < workbook.getNumNames() ; ++i){NameRecord nameRecord = workbook.getNameRecord(i);HSSFName name = new HSSFName(this, nameRecord, workbook.getNameCommentRecord(nameRecord));names.add(name);}}
/*** add a row to the sheet** @param addLow whether to add the row to the low level model - false if its already there*/private void addRow(HSSFRow row, boolean addLow) {_rows.put(Integer.valueOf(row.getRowNum()), row);if (addLow) {_sheet.addRow(row.getRowRecord());}boolean firstRow = _rows.size() == 1;if (row.getRowNum() > getLastRowNum() || firstRow) {_lastrow = row.getRowNum();}if (row.getRowNum() < getFirstRowNum() || firstRow) {_firstrow = row.getRowNum();}}

excel数据行读取到内存的存储结构如下:

三、解决方案

poi官网给了一种大批量数据写入的方法,使用SXXFWorkbook类进行大批量写入操作解决了这个问题,可以监控该样例,我们会发现整体内存呈现锯齿状,能够及时回收,内存相对比较平稳。

package org.bird.poi;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.junit.Assert;public class XSSFWriter {private static SXSSFWorkbook wb;public static void main(String[] args) throws IOException {wb = new SXSSFWorkbook(10000);Sheet sh = wb.createSheet();  for(int rownum = 0; rownum < 100000; rownum++){  Row row = sh.createRow(rownum);  for(int cellnum = 0; cellnum < 10; cellnum++){  Cell cell = row.createCell(cellnum);  String address = new CellReference(cell).formatAsString();  cell.setCellValue(address);  }  }  // Rows with rownum < 900 are flushed and not accessible  for(int rownum = 0; rownum < 90000; rownum++){  Assert.assertNull(sh.getRow(rownum));  }  // ther last 100 rows are still in memory  for(int rownum = 90000; rownum < 100000; rownum++){  Assert.assertNotNull(sh.getRow(rownum));  }  URL url = XSSFWriter.class.getClassLoader().getResource("");FileOutputStream out = new FileOutputStream(url.getPath() + File.separator + "wirter.xlsx");  wb.write(out);  out.close();  // dispose of temporary files backing this workbook on disk  wb.dispose();  }
}

推荐

主流Java进阶技术(学习资料分享)

Java面试题宝典

加入Spring技术开发社区

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!

POI大量数据读取内存溢出分析及解决方案相关推荐

  1. Java 中如何解决 POI 读写 excel 几万行数据时内存溢出的问题?(附源码)

    >>号外:关注"Java精选"公众号,菜单栏->聚合->干货分享,回复关键词领取视频资料.开源项目. 1. Excel2003与Excel2007 两个版本 ...

  2. java内存溢出分析工具:jmap使用实战

    java内存溢出分析工具:jmap使用实战 在一次解决系统tomcat老是内存撑到头,然后崩溃的问题时,使用到了jmap.  1 使用命令  在环境是linux+jdk1.5以上,这个工具是自带的,路 ...

  3. 内存溢出分析之工具篇

    内存溢出分析之工具篇 转载于:https://www.cnblogs.com/lwmp/p/9850446.html

  4. JVM 调优实战--jmap的使用以及内存溢出分析

    目录 jmap的使用以及内存溢出分析 查看内存使用情况 查看内存中对象数量及大小 将内存使用情况dump到文件中 通过jhat对dump文件进行分析 通过MAT工具对dump文件进行分析 MAT介绍 ...

  5. linux环境下内存溢出分析MAT

    文章目录 1 下载及安装mat 1.1 下载地址 1.2 查看服务器版本 1.3 下载安装 2 配置 3 运行 4 分析 1 下载及安装mat 1.1 下载地址 https://www.eclipse ...

  6. JAVA内存泄露分析和解决方案及WINDOWS自带查看工具

    JAVA内存泄露分析和解决方案及WINDOWS自带查看工具 Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可是布署到远端就会出现内存无限制的增长,最后系统瘫痪,那么如何最 ...

  7. Linux下tomcat内存溢出分析及优化

    为什么80%的码农都做不了架构师?>>>    常见的内存溢出有以下两种: java.lang.OutOfMemoryError: PermGen space java.lang.O ...

  8. POI解决读入Excel内存溢出

    POI读取excel表 下面是结构图 大批量数据读取的问题 在项目中遇到二十万行数据的excel用poi读取会内存溢出,一般方法是调大tomcat的内存,但是调到2048M还是会内存溢出报错 poi官 ...

  9. Java内存溢出分析

    内存溢出与数据库锁表的问题,可以说是开发人员的噩梦,一般的程序异常,总是可以知道在什么时候或是在什么操作步骤上出现了异常,而且根据堆栈信息也很容易定位到程序中是某处出现了问题.内存溢出与锁表则不然,一 ...

最新文章

  1. spring-amqp整合rabbitmq消费者配置和代码
  2. RT-Thread GCC VSCode等开源工具链 在智能小车制作中的应用
  3. 如何为从1到10万用户的应用程序,设计不同的扩展方案?
  4. mongoDB的shell数组操作器
  5. TensorFlow for Hackers - Part III
  6. [Lua学习]简单链表
  7. 数据结构(三)之单链表反向查找
  8. java中遍历树形菜单,你可能不知道还有这样的方法
  9. Eclipse把默认为Gbk的编码变为UTF-8
  10. Python遍历字典的四种方法对比
  11. 创建接口匿名实现类的对象的四种方法
  12. Node 中的开发环境与生产环境 和 使用Morgan打印请求信息
  13. Qt从入门到放弃_0x01:建立项目
  14. Delphi -- 农历算法
  15. 计算机二级考试谁监考,【考证】你们要的计算机二级考试攻略来了!!!
  16. mysql查询父子关系树_数据库 SQL 遍历父子关系表(二叉树)获得所有子节点 所有父节点...
  17. 设计模式:简单的鸭子模型(入门)
  18. 雅诗兰黛公司宣布晋升Stéphane de La Faverie为集团总裁
  19. 微信发红包的测试用例功能点
  20. 科普系列:AUTOSAR与OSEK网络管理比较(上)

热门文章

  1. 史上最牛“老赖”,如今走下神坛:骗遍全国,牛皮终于吹破了!
  2. 库克微微一笑:苹果市值再次突破万亿美元大关
  3. 上海特斯拉自燃事件终于有结果了:没有系统缺陷 单个电池模组故障
  4. GPIO应用开发方法【ZT】
  5. 浅谈网络通信中的流量整形
  6. 智能控制第四版程序代码_晋中成本低的智能水表方便了人们生活
  7. 被尘封的故事技能点bug_王者荣耀体验服更新,多名英雄技能优化,瑶妹玩家却坐不住了...
  8. 使用dlib 进行人脸识别
  9. go https client
  10. 使用cppcheck检测代码警告、错误