带stringbuilder的java outOfMemoryError

带stringbuilder的java outOfMemoryError,java,string,heap,stringbuilder,out-of-memory,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.

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

}

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

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

每个字符是两个字节。您拥有原始输入和被替换的输出(在缓冲区中),并且在内存不足时请求第三个副本

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


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

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

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

  • 如果还没有,请尝试适当地扩大堆大小(如果适用)
  • StringBuffer
    指定一个与给定
    字符串长度相同的初始大小
    buffer
    。在扩展
    StringBuffer
    的过程中,这样可以减少不必要的内存使用。我假设它只是替换原始字符串的某些字,长度应该大致相同
  • 如果可能,您可以返回生成的
    StringBuffer
    对象。只有在删除原始
    String
    对象后才能调用其
    toString()

  • 我同意其他的回答…但是…仅仅因为异常发生在那里并不一定意味着这就是问题所在。你很可能在其他地方,而这恰好是它被揭示的地方。你应该运行一个测试来检查内存使用情况,并确实验证哪些对象没有被收集。

    我认为问题是当Matcher将字符序列附加到生成器时,使用ith
    StringBuilder.append()

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

    是的!不要在内存中缓冲,否则会耗尽内存,特别是当I/O超过2MB时


    修复和追加文本的推荐链接:

    一个“大文件”有多大"? 可能是因为您没有为JVM分配足够的内存。请显示错误文本以供进一步调查。OString长度为2769348的纯字符串如何?大部分字符串是捕获的照片的下一个字符串。如果您的处理是基于逐行工作的,那么您可以使用以下命令:
    BufferedReader rd=new BufferedReader(new FileReader(“/path/to/your/file”)并在
    while
    循环中调用
    readLine()
    ,然后对更改的行执行替换并执行任何必要的操作。扩大堆大小工作。