java OutOfMemoryError com stringbuilder
-
19-09-2019 - |
Pergunta
Estou recebendo um OutOfMemoryError java quando eu chamar esse método - eu estou usando-o em um loop para analisar muitos arquivos grandes em sequência. meu palpite é que result.toString()
não está recebendo lixo coletado corretamente durante o loop. em caso afirmativo, como eu deveria consertá-lo?
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;
}
Solução
Escrito desta forma, você vai precisar de cerca de 6 bytes de memória para cada caractere no arquivo.
Cada personagem é de dois bytes. Você tem a entrada bruta, a saída substituído (no buffer), e você está pedindo uma terceira cópia quando você ficar sem memória.
Se o arquivo é codificado em algo como ASCII ou ISO-8859-1 (a codificação de caracteres de byte único), que significa que será seis vezes maior na memória do que no disco.
Você pode alocar mais memória para o processo, mas uma solução melhor poderia ser a de processar a entrada "streamwise" -Read, digitalização, e gravar os dados sem carregar tudo na memória ao mesmo tempo.
Outras dicas
Se os seus arquivos a serem processados ??são todos muito grande, dizem que mais de um MB algumas centenas, então você realmente deve ir com fluxo de processamento em vez desta maneira "carregar tudo na memória", assim como @erickson sugeriu.
Caso contrário, há algumas coisas que você poderia tentar, tudo para reduzir o uso de memória, tanto quanto possível:
- Tente adequadamente ampliar o tamanho da pilha ainda se não (quando aplicável).
- Dar
StringBuffer
um tamanho inicial igual ao comprimento do dadoString
buffer
. Isso deve reduzir o uso de memória desnecessária, enquanto a expansão doStringBuffer
no processo. Presumo que só está substituindo certas palavras da string original e deve ser mais ou menos o mesmo de comprimento. - Se possível, talvez você possa retornar o objeto
StringBuffer
gerado em vez disso. Chamando seutoString()
somente depois de se livrar do objetoString
originais.
Eu acho o problema com StringBuilder.append()
. Quando Matcher anexa seqüência de caracteres para o Construtor.
Conforme explicado no artigo sobre OutOfMemoryError com StringBuilder / StringBuffer , é um problema conhecido que de acréscimo () irá duplicar a capacidade de se chars
tampão interno se a capacidade não é suficiente.
Ir para fluxos como sugerido por Erickson.
Concordo com as outras respostas ... mas ... simplesmente porque a exceção ocorre lá não necessariamente significa que é o problema. Você pode muito bem estar vazamento de memória em outro lugar e que só acontece de ser o lugar que é revelado. Você deve executar um profiler para examinar o uso de memória e verificar exatamente o que os objetos não estão sendo coletados.
Sim! Não armazena na memória caso contrário você vai ficar sem ele, especialmente se você está indo mais de 2MB de I / O.
link Recomendado para fixação e anexar texto: http: // java.ittoolbox.com/documents/appending-data-to-a-file-18786
Você poderia tentar retornar um StringBuffer
e defini-lo como null
após o uso.