OutOfMemoryError: Heap Space - Memory Leak

Olá pessoALL.

Minha aplicação J2EE está consumindo muita memória e o consumo não para de crescer…
Já aumentei o Heap Space (de 512 para 1024MB) mais mesmo assim não adiantou muito, depois de um tempo o espaço é ocupado até exibir a exception: Java.lang.OutOfMemoryError: Java heap space

Função da aplicação: Executar SQLS e gerar um relatório em XML que será consumido por um WService.
Tenho várias classes que implementam uma interface (IGeraXML) e um timer EJB que verificar a cada 10 segundos qual XML deve ser gerado, ou seja, qual instancia/classe deve ser executada.

As instancias das classes são via Injection (CDI - Weld - @Injection e Instance ).

Segue o log do VisualVM.



Seria interessante colocar o código onde vc acha que está sendo gerado o alto consumo…

Mas pelo que deu pra ver…vc deve estar usando sempre o mesmo hashMap para alocar parametros para pesquisas ou geração de relatórios… e nunca são desalocados…ficando cada vez maiores a cada execução… dá uma olhada no código e verifica isso… se os hashmap são globais ou algo assim ou o escopo deles na sua aplicação…

[quote=leopoldof]Seria interessante colocar o código onde vc acha que está sendo gerado o alto consumo…

Mas pelo que deu pra ver…vc deve estar usando sempre o mesmo hashMap para alocar parametros para pesquisas ou geração de relatórios… e nunca são desalocados…ficando cada vez maiores a cada execução… dá uma olhada no código e verifica isso… se os hashmap são globais ou algo assim ou o escopo deles na sua aplicação…[/quote]

Aí é que está outro problema. Não sei onde está o “gargalo”.
Apenas faço um @Injection dos objetos que utilizo para geração e persistência dos dados.
Seria interessante eu apontar para “null” todas as instâncias das classe após a execução de um SQL/XML?

Alguém???

Muita coisa pode estar acontecendo…não existe resposta exata e bala de prata para isso. Veja - http://fernandofranzini.wordpress.com/2011/12/13/a-famosa-falta-de-memoria-java-lang-outofmemoryerror/

Fernando,

Tem um método estático que gera os XML’s dos relatórios, retorna uma String gigantesca (XStream).
Ele é usado por todas as classes que geram relatórios (cerca de umas 25 classes) a todo o momento.
Isso pode gerar gargalo na heap? Mesmo sendo um método estático?

Desculpe se estou falando besteira.

Pode ser sim…
O coletor faz o ciclo…se esta estourando memoria é por causa de 2 motivos:
1 - a solução esta alocando e não esta liberando para ser coletado. Nesse caso tem que otimizar o código. Não vai adiantar aumentar a memoria pq vc não libera…
2 - a solução ja esta otimizado e ainda sim não é suficiente. Nesse caso sua infra não esta suportando a demanda atual. Vc precisa escalar vertical ou horizontal.

[quote=FernandoFranzini]Pode ser sim…
O coletor faz o ciclo…se esta estourando memoria é por causa de 2 motivos:
1 - a solução esta alocando e não esta liberando para ser coletado. Nesse caso tem que otimizar o código. Não vai adiantar aumentar a memoria pq vc não libera…
2 - a solução ja esta otimizado e ainda sim não é suficiente. Nesse caso sua infra não esta suportando a demanda atual. Vc precisa escalar vertical ou horizontal.[/quote]

Neste caso,
Qual seria a melhor solução?
Instanciar o objeto de geração de XML (new()) e depois fecha-lo (no finally{})?

Atual:

 XStreamHelper.geraXML(param);

Mudança (para cada chamada e geração de um novo XML):


XStreamHelper xml =null;
try {
    xml = new XStreamHelper();
    xml.geraXML(param);
} finally {
    xml = null;
}

A melhor solução OTIMIZAR seu código no possível = descobrir as coisas que estão segurando objetos e tomar alguma medida contra isso. Vc pode reduzir o escopo ou aumentar, reiniciando o estado do objeto. No meu artigo eu deu algumas sugestões, mas cada solução é um caso.
Eu não tenho como dizer oque é sem ver o código da solução…
Otimize, faça testes de carga, stress, monitore os ciclos do GC…veja oque vc consegue ganhar.

[quote=FernandoFranzini]A melhor solução OTIMIZAR seu código no possível = descobrir as coisas que estão segurando objetos e tomar alguma medida contra isso. Vc pode reduzir o escopo ou aumentar, reiniciando o estado do objeto. No meu artigo eu deu algumas sugestões, mas cada solução é um caso.

Isso q vc falou pode ser sim…

Otimize, faça testes de carga, stress, monitore os ciclos do GC…veja oque vc consegue ganhar.

[/quote]

Ok…
Vou fazer alguns testes de stress e verificar onde está o possível “gargalo”.
Qualquer coisa, volto aqui de novo.
Obrigado Fernando…

Teu artigo está ótimo, parabéns!

Com os dados que temos no post não dá para te ajudar. O que noto, pelos relatórios do visualvm, é que tem muita coisa ficando presa, noto pela quantidade de instâncias de Map em memória.

Verifique se você tem instâncias estáticas, pois elas podem ir acumulando coisas e com o tempo estourar memória.

[quote=garcia-jj]Com os dados que temos no post não dá para te ajudar. O que noto, pelos relatórios do visualvm, é que tem muita coisa ficando presa, noto pela quantidade de instâncias de Map em memória.

Verifique se você tem instâncias estáticas, pois elas podem ir acumulando coisas e com o tempo estourar memória.

[/quote]

Como no caso que citei logo acima? Um método estático retornando uma String gigantesca?

Eu citei instâncias/referências estáticas, e não métodos estáticos.

Se você está supondo que o que tá esgotando a memória é algo mais “baixo nível” tipo alguma biblioteca que você tá usando sem ter total conhecimento do funcionamento interno, tenta modularizar o programa, isolar cada chamada em um programa teste e descobrir qual é a biblioteca que tá alocando tanta memória assim. Quando descobrir posta a biblioteca específica e tentamos dar alternativas.

Caso você acha que é alguma parte do seu código que está fazendo isso, poste seu código aqui (a parte que você mesmo implementa) e fica mais fácil de achar.

Alocação de memória é problema específico, que varia de software pra software, não tem uma solução geral, você tem que fazer uma análise e vir com algo mais específico.