将数据写入 CSV 文件时出现内存不足错误
Getting Out of memory error while writing data into CSV file
我正在尝试导出 CSV 文件中的数据,有 10 万行要导出。我收到 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误和其他警告消息。
我已将堆内存增加到 8GB,但仍然出现 out-of-memory 错误。如果需要更改任何代码或查看服务器配置设置,请提供帮助。
我正在使用 SpringMVC4、Java 1.8 和 Tomcat 版本 7 进行开发。
我有一个带有图像图标的 UI 页面(导出到 excel)以下载报告
将数据加载到 CSV 文件的步骤:
- 使用 PreparedStatement 从数据库 table 中提取数据。
- 应用于跳过行的条件。
- 数据附加在 object 数组中。
- Header 列是使用 PreparedStatement 形成的(header 列因步骤 1 而异)。
- 数据从 object 数组加载到 CSV 文件并使用 XSSFWorkbook 写入文件。
将数据写入 CSV 文件时,第 5 步出现内存不足错误。
代码片段
//fetch data
String query="select partid, partnumber, partname from tparts";
List<Map<String, Object>> rows = jdbcTemplate.queryForList(query);
for(Map<String, Object> row : rows){
String strPartId = row.get("partid").toString();
String strPartName = (String)row.get("partname");
}
//xls download
public byte[] ExportPartsData(PartsRequestVO reqVo, PartsDataVo partsDataVo) throws Exception {
XSSFWorkbook xssWrkBook = new XSSFWorkbook();
XSSFSheet xssSheet = xssWrkBook.createSheet();
List<Object[]> lstObj = partsDataVo.getPartsData();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
xssWrkBook.write(outStream);
return outStream.toByteArray();
错误日志
Handler处理失败;嵌套异常是 java.lang.OutOfMemoryError: GC overhead limit exceeded
在 org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1303)
在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:977)
在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
在 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
在 javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
在 javax.servlet.http.HttpServlet.service 内部(HttpServlet.java:741)
在 sun.reflect.GeneratedMethodAccessor76.invoke(来源不明)
在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
在 java.lang.reflect.Method.invoke(Method.java:498)
WARN JDBC 要重置的连接与最初准备的连接不相同 - 请确保使用连接释放模式 ON_CLOSE(默认)和 运行 针对 Hibernate 4.2+(或者将 HibernateJpaDialect 的 prepareConnection 标志切换为 false
异常:java.lang.OutOfMemoryError 从线程中的 UncaughtExceptionHandler 抛出
尝试使用 Spring 批处理 excel:https://github.com/spring-projects/spring-batch-extensions/tree/main/spring-batch-excel
您可以使用 StreamingXlsxItemReader,它专为读取大数据文件而设计。
引用自以下项目自述文件:
To reduce the memory footprint the StreamingXlsxItemReader can be
used, this will only keep the current row in memory and discard it
afterward. Not everything is supported while streaming the XLSX file.
It can be that formulas don’t get evaluated or lead to an error.
从您的日志中看不到它调用异常调用。假设是
xssWrkBook.write(outStream);
考虑一下,ByteArrayOutputStream 限制为 2GB,并且在 SUN 运行时的情况下,它的分配概念没有优化。您无论如何都想写入 CSV 文件!?
我正在尝试导出 CSV 文件中的数据,有 10 万行要导出。我收到 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误和其他警告消息。
我已将堆内存增加到 8GB,但仍然出现 out-of-memory 错误。如果需要更改任何代码或查看服务器配置设置,请提供帮助。
我正在使用 SpringMVC4、Java 1.8 和 Tomcat 版本 7 进行开发。
我有一个带有图像图标的 UI 页面(导出到 excel)以下载报告
将数据加载到 CSV 文件的步骤:
- 使用 PreparedStatement 从数据库 table 中提取数据。
- 应用于跳过行的条件。
- 数据附加在 object 数组中。
- Header 列是使用 PreparedStatement 形成的(header 列因步骤 1 而异)。
- 数据从 object 数组加载到 CSV 文件并使用 XSSFWorkbook 写入文件。
将数据写入 CSV 文件时,第 5 步出现内存不足错误。
代码片段
//fetch data
String query="select partid, partnumber, partname from tparts";
List<Map<String, Object>> rows = jdbcTemplate.queryForList(query);
for(Map<String, Object> row : rows){
String strPartId = row.get("partid").toString();
String strPartName = (String)row.get("partname");
}
//xls download
public byte[] ExportPartsData(PartsRequestVO reqVo, PartsDataVo partsDataVo) throws Exception {
XSSFWorkbook xssWrkBook = new XSSFWorkbook();
XSSFSheet xssSheet = xssWrkBook.createSheet();
List<Object[]> lstObj = partsDataVo.getPartsData();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
xssWrkBook.write(outStream);
return outStream.toByteArray();
错误日志
Handler处理失败;嵌套异常是 java.lang.OutOfMemoryError: GC overhead limit exceeded 在 org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1303) 在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:977) 在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) 在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 在 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:660) 在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 在 javax.servlet.http.HttpServlet.service 内部(HttpServlet.java:741) 在 sun.reflect.GeneratedMethodAccessor76.invoke(来源不明) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498)
WARN JDBC 要重置的连接与最初准备的连接不相同 - 请确保使用连接释放模式 ON_CLOSE(默认)和 运行 针对 Hibernate 4.2+(或者将 HibernateJpaDialect 的 prepareConnection 标志切换为 false
异常:java.lang.OutOfMemoryError 从线程中的 UncaughtExceptionHandler 抛出
尝试使用 Spring 批处理 excel:https://github.com/spring-projects/spring-batch-extensions/tree/main/spring-batch-excel
您可以使用 StreamingXlsxItemReader,它专为读取大数据文件而设计。
引用自以下项目自述文件:
To reduce the memory footprint the StreamingXlsxItemReader can be used, this will only keep the current row in memory and discard it afterward. Not everything is supported while streaming the XLSX file. It can be that formulas don’t get evaluated or lead to an error.
从您的日志中看不到它调用异常调用。假设是
xssWrkBook.write(outStream);
考虑一下,ByteArrayOutputStream 限制为 2GB,并且在 SUN 运行时的情况下,它的分配概念没有优化。您无论如何都想写入 CSV 文件!?