java outOfMemoryError с построителем строк

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

}

person user276712    schedule 12.03.2010    source источник
comment
Насколько велик большой файл? Возможно, вы просто не выделяете достаточно памяти для JVM.   -  person Ash    schedule 12.03.2010
comment
Показать текст ошибки для дальнейших исследований.   -  person Artic    schedule 12.03.2010
comment
как насчет чистой строки длины OString: 2769348? Большая часть строки — это следующая строка захваченных фотографий.   -  person Raju yourPepe    schedule 09.07.2013


Ответы (6)


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

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

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

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

person erickson    schedule 12.03.2010
comment
Недурно. Если ваша обработка основана на построчной работе, вы можете просто использовать это: BufferedReader rd = new BufferedReader(new FileReader("/path/to/your/file")); и вызвать readLine() в цикле while, затем выполнить замены и сделать все необходимое с измененной строкой. - person dimitarvp; 12.03.2010

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

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

  1. Попробуйте правильно увеличить размер кучи, если это еще не сделано (если применимо).
  2. Дайте StringBuffer начальный размер, равный длине данного String buffer. Это должно уменьшить ненужное использование памяти при расширении StringBuffer в процессе. Я предполагаю, что он заменяет только определенные слова исходной строки и должен быть более или менее одинаковым по длине.
  3. Если возможно, возможно, вместо этого вы могли бы вернуть сгенерированный объект StringBuffer. Вызов его toString() только после того, как вы избавитесь от исходного объекта String.
person bryantsai    schedule 12.03.2010
comment
увеличение размера кучи воков. - person Mehul Joisar; 10.02.2015

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

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

person Mohammed    schedule 17.09.2010

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

person nicerobot    schedule 12.03.2010

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

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

person user464034    schedule 01.10.2010

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

person fastcodejava    schedule 12.03.2010