java outOfMemoryError 与 stringbuilder

Posted

技术标签:

【中文标题】java outOfMemoryError 与 stringbuilder【英文标题】:java outOfMemoryError with stringbuilder 【发布时间】:2011-01-26 17:25:12 【问题描述】:

当我调用这个方法时,我得到一个 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;


【问题讨论】:

“大文件”有多大?可能是您没有为 JVM 分配足够的内存。 显示错误文本以供进一步调查。 OString Length: 2769348 的纯字符串怎么样?大部分字符串是拍摄照片的nexString 【参考方案1】:

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

每个字符是两个字节。您有原始输入、替代输出(在缓冲​​区中),当内存不足时,您正在请求第三个副本。

如果文件以 ASCII 或 ISO-8859-1(单字节字符编码)之类的方式编码,这意味着它在内存中的大小将是磁盘上的六倍。

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

【讨论】:

点赞。如果您的处理是基于逐行工作的,您可以很好地使用这个:BufferedReader rd = new BufferedReader(new FileReader("/path/to/your/file")); 并在while 循环中调用readLine(),然后进行替换并对更改的行执行任何必要的操作。 【参考方案2】:

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

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

    如果还没有(如果适用)尝试适当地扩大堆大小。 为StringBuffer 赋予一个与给定String buffer 的长度相同的初始大小。这应该会减少不必要的内存使用,同时在进程中扩展StringBuffer。我假设它只是替换原始字符串的某些单词,并且长度应该或多或少相同。 如果可能,也许您可​​以返回生成的StringBuffer 对象。只有在你摆脱了原来的String 对象之后才调用它的toString()

【讨论】:

扩大堆大小炒锅。【参考方案3】:

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

正如关于OutOfMemoryError with StringBuilder/StringBuffer 的文章中所解释的,如果内部缓冲区chars 容量不足,append() 将使容量翻倍是一个已知问题。 按照 Erickson 的建议选择流。

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:

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

【讨论】:

以上是关于java outOfMemoryError 与 stringbuilder的主要内容,如果未能解决你的问题,请参考以下文章

java stackoverflowerror与outofmemoryerror区别(转)

C#连接solr时提示 java内存异常 (jetty和tomcat哪个更High) java.lang.OutOfMemoryError

java 内存溢出-与gc

OutOfMemoryError异常 和 StackOverflowError异常

OutOfMemoryError异常——Java堆溢出。

jvm,深入理解java虚拟机,实战:OutOfMemoryError异常