java outOfMemoryError с stringbuilder

Я получаю 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;

}
7
задан user276712 12 March 2010 в 07:06
поделиться

4 ответа

При таком написании вам потребуется примерно 6 байт памяти для каждого символа в файле.

Каждый символ состоит из двух байтов. У вас есть необработанный ввод, замененный вывод (в буфере), и вы запрашиваете третью копию, когда у вас заканчивается память.

Если файл закодирован в чем-то вроде ASCII или ISO-8859-1 (однобайтовая кодировка символов), это означает, что он будет в шесть раз больше в памяти, чем на диске.

Вы можете выделить процессу больше памяти, но лучшим решением может быть обработка ввода «поточно» - чтение, сканирование и запись данных, не загружая их все сразу в память.

7
ответ дан 6 December 2019 в 12:48
поделиться

Вы можете попробовать вернуть StringBuffer и установить для него значение null после использования.

0
ответ дан 6 December 2019 в 12:48
поделиться

Я согласен с другими ответами... но... просто потому, что исключение происходит там, не обязательно означает, что это проблема. Вы вполне можете быть утечкой памяти в другом месте, и это просто место, где это раскрывается. Вы должны запустить profiler, чтобы проверить использование памяти и точно проверить, какие объекты не собираются.

1
ответ дан 6 December 2019 в 12:48
поделиться

Если все обрабатываемые файлы очень большие, скажем, более нескольких сотен МБ, то вам действительно следует использовать потоковую обработку вместо этого способа "загрузки всех файлов в память", как предложил @erickson.

В противном случае, есть несколько вещей, которые вы можете попробовать, все для уменьшения использования памяти насколько это возможно:

  1. Попробуйте правильно увеличить размер кучи, если это еще не сделано (когда это применимо).
  2. Дайте StringBuffer начальный размер, равный длине данного String buffer. Это должно уменьшить ненужное использование памяти при расширении StringBuffer в процессе. Я предполагаю, что он заменяет только определенные слова исходной строки и должен быть более или менее одинаковой длины.
  3. Если возможно, может быть, вы могли бы возвращать сгенерированный объект StringBuffer вместо этого. Вызывая его toString() только после того, как вы избавитесь от исходного объекта String.
5
ответ дан 6 December 2019 в 12:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: