Я получаю 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 байт памяти для каждого символа в файле.
Каждый символ состоит из двух байтов. У вас есть необработанный ввод, замененный вывод (в буфере), и вы запрашиваете третью копию, когда у вас заканчивается память.
Если файл закодирован в чем-то вроде ASCII или ISO-8859-1 (однобайтовая кодировка символов), это означает, что он будет в шесть раз больше в памяти, чем на диске.
Вы можете выделить процессу больше памяти, но лучшим решением может быть обработка ввода «поточно» - чтение, сканирование и запись данных, не загружая их все сразу в память.
Вы можете попробовать вернуть StringBuffer
и установить для него значение null
после использования.
Я согласен с другими ответами... но... просто потому, что исключение происходит там, не обязательно означает, что это проблема. Вы вполне можете быть утечкой памяти в другом месте, и это просто место, где это раскрывается. Вы должны запустить profiler, чтобы проверить использование памяти и точно проверить, какие объекты не собираются.
Если все обрабатываемые файлы очень большие, скажем, более нескольких сотен МБ, то вам действительно следует использовать потоковую обработку вместо этого способа "загрузки всех файлов в память", как предложил @erickson.
В противном случае, есть несколько вещей, которые вы можете попробовать, все для уменьшения использования памяти насколько это возможно:
StringBuffer
начальный размер, равный длине данного String
buffer
. Это должно уменьшить ненужное использование памяти при расширении StringBuffer
в процессе. Я предполагаю, что он заменяет только определенные слова исходной строки и должен быть более или менее одинаковой длины. StringBuffer
вместо этого. Вызывая его toString()
только после того, как вы избавитесь от исходного объекта String
.