【问题标题】:java.lang.OutOfMemoryError: Java heap space?java.lang.OutOfMemoryError:Java 堆空间?
【发布时间】:2015-05-14 13:18:27
【问题描述】:

我正在使用 StringBuffer 对象将列表对象写入 CSV 文件,当列表包含的数据较少时,我们的逻辑工作正常,但是当列表中有大量数据时,就会出现问题,我得到了错误:java.lang.OutOfMemoryError: Java heap space problem

代码sn-p如下:

StringBuffer report = new StringBuffer();
String[] column = null;
StringReader stream = null;
for (MassDetailReportDto dto: newList.values()) {
 int i = 0;
  column = new String[REPORT_INDEX];
  column[i++] = dto.getCommodityCode() == null ? " " :   dto.getCommodityCode();
  column[i++] = dto.getOaId() == null ? " " : dto.getOaId();
  //like this we are calling some other getter methods
  //After all getter methods we are appending columns to stringBuffer object
  report.append(StringUtils.join(column, PIPE));
  report.append(NEW_LINE);
  //now stringbuffer object we are writing to file
  stream = new StringReader(report.toString());
  int count;
  char buffer[] = new char[4096];
  while ((count = stream.read(buffer)) > -1) {
    //writing into file
    writer.write(buffer, 0, count);
  }
  writer.flush();
  //clearing the buffer
  report.delete(0, report.length());
}

错误是:

java.lang.OutOfMemoryError: Java heap space
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:99)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:393)
at java.lang.StringBuilder.append(StringBuilder.java:120)

能否请您查看上面的代码 sn-p 并帮助我,这将是很大的帮助。

【问题讨论】:

  • 您可以使用java-Xmx 选项来增加堆空间。例如:java -Xmx1024m Main
  • 您可以根据上面的评论增加 Java 可用的内存量。或者,您可以查看您的逻辑并考虑是否真的需要在 for 循环的每次迭代中将整个列表写入 writer 时将其放入 report
  • 另外 - 当您提供的 sn-p 无法编译时,很难帮助您提供查询的详细信息 - 您将 column 数组设置为 null 但然后尝试使用column[i++] = .... 此外,i 未定义。你能确保你提供一个可编译的Minimal, complete and verifiable example吗?
  • 是的,理查德,我们增加了堆大小,我们必须将总列表对象写入文件!我们已经定义了所有参数,即使它适用于少量数据,只有大量数据存在问题。以上代码为示例代码。
  • 这段代码看起来很奇怪。除了已经提到的问题:您创建了一个StringBuffer,您将所有数据附加到该SringBuffer 的唯一目的是稍后将SringBuffer 的内容写入OutputStream。为什么不直接写入流?使用 BufferedWriter 而不是自己滚动。并发布工作代码,而不是复制粘贴的内容,这不可能是您正在运行的代码。

标签: java file csv stringbuffer


【解决方案1】:

column 在哪里初始化?我没看到。但似乎这可能是罪魁祸首。您正在构建一个字符串数组而不将其清除。 column[i++] 。你在哪里清除那个数组?它的作用域应该是循环体,而不是循环体之外。因此,在循环内,声明您的 String[] column 并在该范围内使用它。

【讨论】:

  • 是的,我在初次发帖后就看到了。我已经更改了答案以反映它。
  • 感谢 Madconan,我们正在 for 循环中创建字符串数组 column = new String[REPORT_INDEX];但我错过了发布。代码 sn -p 修改检查一次。
【解决方案2】:

当列表大小足够大时,出现内存不足错误似乎是合乎逻辑的。增加 JVM 堆大小(使用 -Xmx 和 -Xms jvm args)将暂时解决该问题。但是,理想情况下,您应该使用分页访问列表中项目的来源。如果列表是从数据库或网络服务中填充的,则可以很容易地以分页方式访问。

【讨论】:

  • 我们已将 JVM 堆大小增加到 1GB,但仍然面临问题!!..这里对于写入文件后的每一行,我们正在清除缓冲区,但不知道问题到底出在哪里!!
  • 但是列表中的对象本身确实占用了堆空间。因此,最好以分页方式访问它们。
  • 不是堆大小,而是代码。他显然是在要求OOM。
猜你喜欢
  • 2010-12-08
  • 2019-07-10
  • 2019-12-12
  • 2015-04-24
相关资源
最近更新 更多