Java OutOfMemoryError с помощью stringbuilder - PullRequest
7 голосов
/ 12 марта 2010

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

7 голосов
/ 12 марта 2010

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

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

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

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

5 голосов
/ 12 марта 2010

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

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

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

Я считаю, проблема с StringBuilder.append(). Когда Matcher добавляет последовательность символов в Builder.

Как объяснено в статье о OutOfMemoryError с StringBuilder / StringBuffer , это известная проблема, что append () удваивает емкость, если внутренний буфер chars, если емкость недостаточна. Пойдите для потоков, как предложено Эриксоном.

1 голос
/ 01 октября 2010

Да! Не буферизируйте в памяти, иначе у вас не хватит памяти, особенно если вы используете более 2 МБ при вводе / выводе.

Рекомендуемая ссылка для исправления и добавления текста: http://java.ittoolbox.com/documents/appending-data-to-a-file-18786

1 голос
/ 12 марта 2010

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

0 голосов
/ 12 марта 2010

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

...