Excel在Apache POI流API中导出150K+数据时出现JAVA OutOfMemoryError问题

Excel在Apache POI流API中导出150K+数据时出现JAVA OutOfMemoryError问题,java,apache-poi,Java,Apache Poi,我的ApachePOI版本是3.14。我正在尝试将大数据导出到excel?为此,我在internet上找到了解决方案并实现了它 因此,我有以下列表,它来自我的数据库PostgresSQL: 列表结果=新的ArrayList; result.addAlltransactionService.findByInDateRangestatus,fromDate,toDate 然后我按照我上面提到的链接,逻辑完全相同 DateTimeFormatter formatter = DateTimeFor

我的ApachePOI版本是3.14。我正在尝试将大数据导出到excel?为此,我在internet上找到了解决方案并实现了它

因此,我有以下列表,它来自我的数据库PostgresSQL:

列表结果=新的ArrayList; result.addAlltransactionService.findByInDateRangestatus,fromDate,toDate

然后我按照我上面提到的链接,逻辑完全相同

   DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_hh_mm_ss");
    String excelFileName = "Statistics_by_partner" + formatter.format(LocalDateTime.now()) + ".xlsx";
    SXSSFWorkbook wb = (new ExportRevisionResponseExcel()).exportExcel(new String[] { "Status",
        "Request",}, result);
    try {
        ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
        wb.write(outByteStream);
        byte[] outArray = outByteStream.toByteArray();
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setContentLength(outArray.length);
        response.setHeader("Expires:", "0"); // eliminates browser caching
        response.setHeader("Content-Disposition", "attachment; filename=" + excelFileName);
        OutputStream outStream = response.getOutputStream();
        outStream.write(outArray);
        outStream.flush();
        wb.dispose();
        wb.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }`
然而,它仍然给我的记忆错误


顺便说一下,我不认为增加JAVA堆内存是个好主意。

堆空间不足的最可能原因是将整个工作簿流传输到内存中的字节数组缓冲区中

    ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
    wb.write(outByteStream);
这最多可以消耗实际流长度(字节)的三倍。如果希望使用更少的内存,请直接将数据写入响应流:

    OutputStream outStream = response.getOutputStream();
    wb.write(outStream);
显然,这意味着您将无法在响应中设置内容长度。如果这对您来说真的很重要,那么使用一个临时文件来缓冲数据,而不是使用ByteArrayOutputStream


1-BAS使用内部字节[]作为缓冲区。当缓冲区已满时,它将分配一个两倍大小的新缓冲区,并将数据从旧缓冲区复制到新缓冲区。在进行复制时,您有2个字节数组,占到目前为止缓冲的字节数的3倍。

为什么要将整个文件缓冲到字节数组中的内存中,然后写入?为什么不直接写出来?这不是我的解决方案。但据我理解。SXSSFWorkbook stream API我们只能将至少100行数据刷新到内存中,其余的行可以刷新到硬盘永久内存中。我认为,为了写入永久存储器,需要使用缓冲