带有stringbuilder的java outOfMemoryError

时间:2010-03-12 07:07:00

标签: java string heap stringbuilder out-of-memory

当我调用此方法时,我得到一个java outOfMemoryError - 我在循环中使用它来按顺序解析许多大文件。我的猜测是result.toString()在循环过程中没有正确收集垃圾。如果是这样,我该如何解决?

private String matchHelper(String buffer, String regex, String method){
    Pattern abbrev_p = Pattern.compile(regex);//norms U.S.A., B.S., PH.D, PH.D.
    Matcher abbrev_matcher = abbrev_p.matcher(buffer);
    StringBuffer result = new StringBuffer();
    while (abbrev_matcher.find()){
            abbrev_matcher.appendReplacement(result, abbrevHelper(abbrev_matcher));
    }
    abbrev_matcher.appendTail(result);
    String tempResult = result.toString(); //ERROR OCCURS HERE
  return tempResult;

}

6 个答案:

答案 0 :(得分:7)

以这种方式编写,对于文件中的每个字符,您将需要大约 6 字节的内存。

每个字符都是两个字节。你有原始输入,替换输出(在缓冲​​区中),当你内存不足时,你要求第三个副本。

如果文件是用ASCII或ISO-8859-1(单字节字符编码)编码的,那意味着它的内存大6倍于磁盘。

您可以为进程分配更多内存,但更好的解决方案可能是处理输入“streamwise” - 读取,扫描和写入数据,而不是立即将其全部加载到内存中。

答案 1 :(得分:5)

如果要处理的文件都非常大,比如说超过几百MB,那么你真的应该使用流处理而不是“将所有内容加载到内存”,就像@erickson建议的那样。

否则,您可以尝试一些方法,尽可能减少内存使用量:

  1. 如果还没有(适用时),请尝试正确扩大堆大小。
  2. StringBuffer提供与给定String buffer的长度相同的初始尺寸。这样可以在扩展进程中的StringBuffer时减少不必要的内存使用量。我认为它只是替换原始字符串中的某些单词,并且长度应该大致相同。
  3. 如果可能,也许您可​​以返回生成的StringBuffer对象。只有在摆脱原始toString()对象后才调用String

答案 2 :(得分:2)

我认为StringBuilder.append()存在问题。当Matcher将字符序列附加到Builder时。

正如关于OutOfMemoryError with StringBuilder/StringBuffer的文章所解释的,如果容量不足,如果内部缓冲区chars,append()将使容量加倍,这是一个已知问题。 按照埃里克森的建议去寻找溪流。

答案 3 :(得分:1)

我同意其他回复......但是......仅仅因为发生了异常,必然意味着它就是问题所在。你很可能在其他地方leaking memory,而恰好是它所揭示的地方。您应该运行profiler来检查内存使用情况并确切地验证哪些对象没有被收集。

答案 4 :(得分:1)

是的!不要在内存中缓冲,否则如果你的I / O超过2MB,你就会特别用完它。

修复和附加文字的推荐链接:http://java.ittoolbox.com/documents/appending-data-to-a-file-18786

答案 5 :(得分:0)

您可以尝试在使用后返回StringBuffer并将其设置为null