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 ).
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?
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?
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…
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?
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.