【发布时间】:2011-11-25 12:09:13
【问题描述】:
我编写了一个用于管理和运行 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();
不幸的是,当我在我提到的大文件上尝试这个时,我得到了一个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)
...
通过浏览 Jasper 的一些内部结构,看起来无论我如何尝试设置此导出(我也尝试过直接加载和设置 JASPER_PRINT 参数),最终都会调用 JRLoader.loadObject(...)这将尝试将我的整个 500MB 报告加载到内存中(请参阅net.sf.jasperreports.engine.JRAbstractExporter.setInput())。
我的问题是,有没有办法解决这个问题,而不仅仅是在问题上扔内存? 500MB 是可行的,但它不会让我的应用程序非常面向未来,而用于报告执行的JRVirtualizer 解决方案让我希望导出类似的东西。我愿意亲自动手并扩展一些 Jasper 内部类,但出于显而易见的原因,理想的解决方案是 Jasper 自己提供的解决方案。
【问题讨论】:
-
1500+ 页报告,太大了没用。也许考虑分解这些报告。
-
不幸的是,这是将通用工具用于许多不同目的的情况。此报告(CSV 格式)通过脚本导入另一个数据库,而不是人类浏览。
-
我已经向 JasperSoft 提交了功能请求,因为项目预算限制将阻止我寻求更精细的解决方案,例如下面 gpeche 建议的解决方案。 jasperforge.org/projects/jasperreports/tracker/view.php?id=5478
标签: java jasper-reports out-of-memory export-to-csv