Problema de memoria heap ficando lotada no java

Possuo uma aplicação que faz a emissão de relatórios, e possui muita demanda em um dia, notei que ao longo do tempo e dependendo do dia acaba estourando a memoria. Fiz um teste utilizando o JMeter onde enviei 100 requisições para imprimir, e com o JProfiler ao final ele teve uma certa redução de memoria mas muito diferente do que estava no inicio, começando com algo como 200m de memoria, atingindo um pico de 1,5g e finalizando com 1g, quando rodo o GC na mão ele reduz e se mantem, ou seja, tem lixo em memoria. Apliquei o System.GC() no final de cada emissão do relatório, mas como ele trabalha com mult thread quando faço muitas requisições acaba travando, sei que não é uma boa pratica mas fiz so para teste. Utilizo o Birt para emissão do relatório. Teriam alguma sugestão? No código já tentei otimizar de melhor forma que encontrei. Tipo a JVM deveria rodar o GC no final também, parece que so roda durante a emissão.

-Acabei de fazer uma alteração onde eu verifico se é a ultima thread do emissor de relatório e no final chamo o System.GC

Mas apos concluir o relatório você o mantem em memoria ou coloca um null na variavel?

Pelo visto precisa aumentar o limite. Se você envia 100 relatórios para o processamento e dependendo do tamanho vai mesmo estourar a memoria que afinal tem limites.

É preciso pensar em ir colocando em disco a parte processada ou mesmo ir enviando.

Eis o segredo.

Na verdade não sei se iria fazer muita diferença, posso ate testar, mas unica coisa eu passo seria os parâmetros para a emissão do relatorio, o birt fica com toda a função de montar o arquivo e salva-lo

Você não pode se embasar em uma chamada explícita ao coletor de lixo. Essa chamada é apenas uma sugestão à JVM.

Tipo a JVM deveria rodar o GC no final também, parece que so roda durante a emissão.

Depende da implementação e nós, meros mortais, não temos o menor controle sobre isso.

Concordo plenamente com o @j-menezes . Ou você está deixando referências ativas ao trabalho do seu gerador de relatórios ou simplesmente falta recursos pra sua aplicação e vc precisa por mais hardware e/ou configurar a JVM apropriadamente.

1 curtida

Os argumentos da JVM atual estão da seguinte forma uso o Java 7:

  • XX:+UseLargePages
  • XX:+AggressiveOpts
  • XX:+UseFastAccessorMethods
  • Xms18688M
  • Xmx18688M
  • XX:PermSize=128M
  • XX:MaxPermSize=512M
  • XX:+UseG1GC
  • agentpath:/opt/jprofiler12/bin/linux-x64/libjprofilerti.so=port=8849,nowait
  • Dcatalina.base=/usr/share/tomcat
  • Dcatalina.home=/usr/share/tomcat
  • Djava.endorsed.dirs=
  • Djava.io.tmpdir=/var/cache/tomcat/temp
  • Djava.util.logging.config.file=/usr/share/tomcat/conf/logging.properties
  • Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager

Vou dar uma estudada melhor no fonte e verificar o que dar para mudar, mas na jvm nao sei muito o que posso mudar. Se puderem dar uma dica, olhei diversos tipos de argumentos mas nao sei se existe mais algum que se encaixa com a situação, somente esses dois que ainda quero testar e verificar o comportamento:

  • XX: +UseStringDeduplication
  • XX:+HeapDumpOnOutOfMemoryError
1 curtida