【发布时间】:2019-01-14 18:15:27
【问题描述】:
我有一个生成报告的报告网络应用程序。应用程序从数据库中获取数据并将数据存储到StringWriter 对象中。我必须以字节数组格式获取这些数据以创建 csv 文件并将其发送到浏览器。
下面是代码sn-p
return new FileTransfer(fileName, reportType.getMimeType(),
new ByteArrayInputStream(generateCSV(reportType, grid, new DataList(), params).toString().getBytes("UTF-8")));
其中generateCSV 返回一个StringWriter 对象,然后将其转换为字节数组,我调用toString,然后调用getBytes() 方法。下面是generateCSV 方法的样子
StringWriter generateCSV(ReportType reportType, GridConfig grid, DataList dataList, String params) {......}
问题是,当我的报告有大量记录(超过 100 万条)时,getBytes() 方法会失败并显示
java.lang.OutOfMemoryError: 请求的数组大小超过 VM 限制
转换为字符串对象时的整个报表数据包含大量字符(数十亿)。 .getBytes("UTF-8") 方法将其转换为数组,每个数组元素为一个字符。对于 100 万条记录,该字符超出了 MAX JVM ARRAY 大小限制 (https://plumbr.io/outofmemoryerror/requested-array-size-exceeds-vm-limit)。
现在如何避免使用toString().getBytes("UTF-8") 来避免OOM 错误?有没有更好的方法从StringWriter 转换为字节数组?
【问题讨论】:
-
generateCSV方法是否直接将CSV生成为StringWriter? -
什么是
FileTransfer?它真的要求ByteArrayInputStream吗?或者它是否支持Reader(那么你可以使用StringReader)或至少是任意的InputStreams(在这种情况下,Apache Commons 有一个ReaderInputStream)? -
考虑使用临时文件和输入/输出流(或阅读器),而不是将所有内容都保存在内存中。
-
“我必须以字节数组格式获取这些数据以创建 csv 文件并将其发送到浏览器”。我怀疑这种说法是否属实。如果你正在写出文本,你想写成一个正确编码的字节流。
-
Hi @Lino 是的 generateCSV 方法将报告数据生成到 StringWriter 对象中。
标签: java arrays jvm out-of-memory