【问题标题】:OutOfMemoryError: Java heap space on write poi.WorkBook to ByteArrayOutputStream [duplicate]OutOfMemoryError:将 poi.WorkBook 写入 ByteArrayOutputStream 时的 Java 堆空间 [重复]
【发布时间】:2014-10-06 09:45:10
【问题描述】:

我在将 poi HSSFWorkBook 数据写入 ByteArrayOutputStream 时遇到了一些问题。当工作簿超过 10MB 时发生异常。

private Workbook currentWB;

public DataSource getDataSource() throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        **currentWB.write(out);  <-Exception occurs in this line, when workbook writing in  outputstream**
    } finally {
        out.close();
    }
    return new XLSDataSource (TEMPLATE_FILE_NAME, out.toByteArray());
}

 private static class XLSDataSource implements DataSource {
    private final String name;
    private final byte[] content;

    private XLSDataSource(String name, byte[] content) {
        super();
        this.name = name;
        this.content = content;
    }

    @Override
    public String getContentType() {
        return "application/vnd.ms-excel";
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(content);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public OutputStream getOutputStream() throws IOException {
        throw new UnsupportedOperationException();
    }
}

堆栈跟踪:

java.lang.OutOfMemoryError:Java 堆空间 在 java.util.Arrays.copyOf(Arrays.java:2786) 在 java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94) 在 java.io.OutputStream.write(OutputStream.java:58) 在 org.apache.poi.poifs.storage.BigBlock.doWriteData(BigBlock.java:55) 在 org.apache.poi.poifs.storage.BATBlock.writeData(BATBlock.java:227) 在 org.apache.poi.poifs.storage.BigBlock.writeBlocks(BigBlock.java:86) 在 org.apache.poi.poifs.storage.BATBlock.writeBlocks(BATBlock.java:35) 在 org.apache.poi.poifs.storage.BlockAllocationTableWriter.writeBlocks(BlockAllocationTableWriter.java:151) 在 org.apache.poi.poifs.filesystem.POIFSFileSystem.writeFilesystem(POIFSFileSystem.java:398) 在 org.apache.poi.hssf.usermodel.HSSFWorkbook.write(HSSFWorkbook.java:1181) 在 uk.co.itrainconsulting.appbook.core.impl.service.exportBusinessData.XLSRenderer.getDataSource(XLSRenderer.java:79) 在 uk.co.itrainconsulting.appbook.core.impl.service.BusinessExportDataServiceImpl.getDataSource(BusinessExportDataServiceImpl.java:119) 在 uk.co.itrainconsulting.appbook.core.impl.service.BusinessExportDataServiceImpl.sendByEmail(BusinessExportDataServiceImpl.java:75) 在 uk.co.itrainconsulting.appbook.web.bean.BusinessExportDataBean.sendBusinessData(BusinessExportDataBean.java:71) 在 uk.co.itrainconsulting.appbook.web.bean.BusinessExportDataBean$$FastClassByCGLIB$$307f293f.invoke() 在 net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191) 在 org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 在 org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) 在 org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 在 org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) 在 uk.co.itrainconsulting.appbook.web.bean.BusinessExportDataBean$$EnhancerByCGLIB$$1bb626b3.sendBusinessData() 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 com.sun.el.parser.AstValue.invoke(AstValue.java:234) 在 com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297) 在 com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:102) 在 javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:84) 在 org.springframework.faces.webflow.FlowActionListener.processAction(FlowActionListener.java:81) 2014 年 8 月 12 日下午 5:49:50 org.apache.catalina.core.StandardHostValve throwable 警告:异常处理 ErrorPage[exceptionType=java.lang.Throwable, location=/error/internalServerError.jsf] ClientAbortException:java.net.SocketException:软件导致连接中止:套接字写入错误 在 org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:330) 在 org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:296) 在 org.apache.catalina.connector.Response.flushBuffer(Response.java:549) 在 org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:272) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 在 org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861) 在 org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606) 在 org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) 在 java.lang.Thread.run(Thread.java:662) 引起:java.net.SocketException:软件导致连接中止:套接字写入错误 在 java.net.SocketOutputStream.socketWrite0(本机方法) 在 java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92) 在 java.net.SocketOutputStream.write(SocketOutputStream.java:136) 在 org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:761) 在 org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:448) 在 org.apache.coyote.http11.InternalOutputBuffer.flush(InternalOutputBuffer.java:318) 在 org.apache.coyote.http11.Http11Processor.action(Http11Processor.java:987) 在 org.apache.coyote.Response.action(Response.java:186) 在 org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:325) ... 11 更多

【问题讨论】:

  • 什么是ExcelWorkBook,为什么要从字节数组构造它?简单的答案是“不要”。从currentWB 构造它,并用它来写出你最终要写到的任何地方。不要尝试将整个文件加载到内存中,尤其是这样两次。

标签: java excel apache-poi


【解决方案1】:

我目前使用的是同一个库,而且从来不用处理这么大的文件 (10MB)。据我所知,这里唯一的限制是 XLSX 行 > 65K 行和 > 100 万列。使用 Writer 的时候也要小心,因为这个操作比较慢。 OutOfMemoryError 不仅可能由 POI 库的使用引起。

更新:

我目前正在使用更新的 XLSX 格式(我不知道这是否重要)并像这样使用它:

`

FileOutputStream fileOutputStream = new FileOutputStream(file)) { 
 workbook.write(fileOutputStream); 
 fileOutputStream.flush();
 fileOutputStream.close(); }

`

我也用:

File file = new File(relativePath);

请注意.close()之前有.flush()

【讨论】:

  • 非常感谢。例子很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
  • 1970-01-01
  • 2013-08-08
相关资源
最近更新 更多