带有stringbuilder的java outOfMemoryError

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

 private String matchHelper(String buffer, String regex, String method){ Pattern abbrev_p = Pattern.compile(regex);//norms USA, BS, 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个字节的内存。

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

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

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

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

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

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

我同意其他回复……但是……仅仅因为发生exception并不一定意味着它就是问题。 你很可能在其他地方泄露记忆 ,而恰好是它所揭示的地方。 您应该运行一个分析器来检查内存使用情况并确切地validation哪些对象没有被收集。

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

正如在关于带有StringBuilder / StringBuffer的OutOfMemoryError的文章中所解释的那样,如果内容缓冲器在容量不足时发生变化,则append()将使容量加倍。 按照埃里克森的建议去寻找溪流。

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

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

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