use*_*712 7 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;
}
Run Code Online (Sandbox Code Playgroud)
以这种方式编写,对于文件中的每个字符,您将需要大约6个字节的内存.
每个字符都是两个字节.你有原始输入,替换输出(在缓冲区中),当你的内存不足时,你要求第三个副本.
如果文件采用ASCII或ISO-8859-1(单字节字符编码)编码,则意味着内存的大小将比磁盘大6倍.
您可以为进程分配更多内存,但更好的解决方案可能是处理输入"streamwise" - 读取,扫描和写入数据,而不是立即将其全部加载到内存中.
如果要处理的文件非常大,例如超过数百MB,那么您真的应该使用流处理,而不要像@erickson所建议的那样,采用“全部加载到内存”的方式。
否则,您可以尝试以下几种方法,以尽可能减少内存使用量:
StringBuffer与给定长度相同的初始大小String buffer。这应该减少不必要的内存使用量,同时扩展StringBuffer进程。我假设它只是替换原始字符串中的某些单词,并且长度应大致相同。StringBuffer对象。toString()仅在摆脱原始String对象后才调用它。