【问题标题】:Jasper report exporting to text results in java.lang.OutOfMemoryError: Java heap spaceJasper 报告导出到文本导致 java.lang.OutOfMemoryError: Java heap space
【发布时间】:2020-09-15 06:23:43
【问题描述】:

目前我正在使用 jasper v 3.7.4

从同一个dataset 导出到任何其他格式(csvxlspdf)时 - 我没有任何问题。

导出到text 抛出:

java.lang.OutOfMemoryError:Java 堆空间位于 java.util.Arrays.copyOf(Arrays.java:3236) 在 java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)

这是我的代码:

    byte[] bytes = null;
    JRTextExporter  exporter = new JRTextExporter();
    ByteArrayOutputStream txtReport = new ByteArrayOutputStream();
    exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
    exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, txtReport);
    exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "mytxt.txt");
    exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
    exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, 2.0F);
    exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, 100.0F);
    exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, 4.0F);
    exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, 50.0F);
    
    exporter.exportReport();
    bytes = txtReport.toByteArray();

    FileOutputStream fos = new FileOutputStream("c:\\myfile.txt")
    System.out.println(bytes.length/1024+" Kbytes");
    fos.write(bytes, 0, bytes.length);
    fos.flush();
    fos.close();

我也使用virtualizer 作为jasperPrint 参数

 JRFileVirtualizer virtualizer = new JRFileVirtualizer(150);
 virtualizer.setReadOnly(false);
 params.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);

但这并没有帮助,并且还会显示以下警告:

警告:参数“REPORT_VIRTUALIZER”已注册,正在跳过 这个。

鉴于csv也是一个“text”文件并且生成时没有任何问题,这有点奇怪 导出到 text 失败。

我为导出器提供的参数可能有问题?

谢谢。

【问题讨论】:

  • @Kayaman 你是部分正确的(关于给定的代码) - 但是上面的代码是为了复制问题而创建的 - 在真实的代码中(在 servlet 内部) - 没有 FileOutput - 一切都是在内存中完成 - 正如我之前所说,cvs 生成完美 - 但文本失败。
  • 如果在实际代码中将报告写入任何流(网络)等,情况仍然相同。此外,如果 csv 生成完美也没关系,你的内存已经用完了。我不知道为什么您会认为成功的 csv 导出将意味着成功的文本导出。文本和csv格式不同,所有文件都是二进制的,“文本文件”只是给人类做的一个区分。
  • 感谢您的 cmets - 非常有帮助 - 当然你是对的 - 我应该直接写到流。另外,我没想到文本报告会填充这么多空格字符 - 这就是结果巨大并给出 OOME 的原因。
  • 一个问题 - 写入临时 ByteArrayOutputStream 的唯一原因是能够在 servlet 的响应中设置 response.setContentLength(bytes.length); 但如果我直接写入流,我不知道内容长度。 ..有没有办法获得这些信息?
  • 好吧,那么你必须做出选择。我会选择低内存选项,因为现在是 2020 年,我在 90 年代做了足够的时间估计。但是,如果您想为您的用户提供该选项,那么您可以增加内存。

标签: java jasper-reports out-of-memory


【解决方案1】:

虽然textcsv 可能都是基于文本的 格式,但它们不是相同 格式,因此占用的空间量不同。

在内存中生成任何东西(通常是报告)是危险的,因为虽然它可能在测试中起作用,但在生产中导致 OOME 的大型报告将造成严重破坏。

在生成事物时使用真实的流。 FileOutputStream,网络流,任何不将内容存储在内存中的适当流。如果您将ByteArrayOutputStream 用于“实际工作”,那么您很可能做错了什么。

【讨论】:

    【解决方案2】:

    立即将报告输出到文件,而不是先收集。

    try (FileOutputStream fos = new FileOutputStream("c:\\myfile.txt");
            BufferedOutputStream bos = new BufferedOutputStream(fos)) {
        JRTextExporter  exporter = new JRTextExporter();
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, bos);
        exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "mytxt.txt");
        exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
        exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, 2.0F);
        exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, 100.0F);
        exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, 4.0F);
        exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, 50.0F);
    
        exporter.exportReport();
    }
    

    【讨论】:

      猜你喜欢
      • 2013-06-06
      • 2016-04-15
      • 1970-01-01
      • 2018-06-15
      • 2012-08-03
      • 2010-12-08
      • 2020-11-30
      • 2013-12-20
      • 2013-05-18
      相关资源
      最近更新 更多