Eri*_*ric 5 java jasper-reports out-of-memory export-to-csv
我编写了一个用于管理和运行 Jasper 报告的 Web 应用程序。最近,我一直在处理一些生成极大(1500+页)输出的报告,并尝试解决由此产生的内存问题。我发现了JRFileVirtualizer,它使我能够以非常有限的内存占用成功运行该报告。然而,我的应用程序的功能之一是它存储以前运行的报告的输出文件,并允许将它们导出为各种格式(PDF、CSV 等)。因此,我发现自己有一个 500+MB 的 .jrprint 文件,并希望将其导出为(例如)按需的 CSV。这是一些简化的示例代码:
JRCsvExporter exporter = new JRCsvExporter();
exporter.setParameter(JRExporterParameter.INPUT_FILE_NAME, jrprintPath);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
exporter.exportReport();
Run Code Online (Sandbox Code Playgroud)
不幸的是,当我在我提到的大文件上尝试执行此操作时,我得到一个OutOfMemoryError:
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.io.ObjectInputStream$HandleTable.grow(ObjectInputStream.java:3421)
at java.io.ObjectInputStream$HandleTable.assign(ObjectInputStream.java:3227)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1744)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at java.util.ArrayList.readObject(ArrayList.java:593)
at sun.reflect.GeneratedMethodAccessor184.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at net.sf.jasperreports.engine.base.JRVirtualPrintPage.readObject(JRVirtualPrintPage.java:423)
...
Run Code Online (Sandbox Code Playgroud)
从浏览 Jasper 的一些内部结构来看,无论我如何尝试设置此导出(我也尝试过JASPER_PRINT直接加载和设置参数),最终都会有一个调用JRLoader.loadObject(...)尝试加载我的整个 500MB 报告进入内存(参见net.sf.jasperreports.engine.JRAbstractExporter.setInput())。
我的问题是,有没有一种方法可以解决这个问题,而不是只用内存来解决问题?500MB 是可行的,但它并不能让我的应用程序面向未来,而且JRVirtualizer报告执行的解决方案让我希望有类似的导出功能。我愿意亲自动手扩展一些 Jasper 内部类,但出于显而易见的原因,理想的解决方案将是 Jasper 本身提供的解决方案。
自从发布这个问题以来,我还向 JasperSoft 提交了功能请求。作为后续行动,有人向我指出了该JRVirtualizationHelper.setThreadVirtualizer方法。此方法允许您设置与当前线程关联的 JRVirtualizer,该 JRVirtualizer 将在 JasperPrint 反序列化期间使用。
我在我的项目中对此进行了测试,结果令人满意。看来我希望存在的功能确实存在,尽管它在 API 中的可见性可能会得到提高。
代码示例:
JRVirtualizer virtualizer = new JRSwapFileVirtualizer(1000, new JRSwapFile(reportFilePath, 2048, 1024), true);
JRVirtualizationHelper.setThreadVirtualizer(virtualizer);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10979 次 |
| 最近记录: |