Amigos,
Trabalho no desenvolvimento de um sistema de gerência de empresas, e venho sofrendo com a confecção de uma tela em específico de um relatório. O Sistema usa Struts e Hibernate, além de uma terceira camada de comunicação que fizemos entre o Struts e o nosso sistema.
Existe uma classe que herda de TilesRequestProcessor, por onde todas as requisições passam antes de serem processadas. Essa classe é feita para lidar com questões de segurança do sistema (permissão de acesso a telas e funcionalidades para cada grupo de usuário).
Dado esse overall, eu tenho a seguinte situação: no relatório sobre o qual falei mais acima, eu tenho duas imagens que são geradas a partir de outras 2 actions, respectivamente, além da action que carregou as informações necessárias para a JSP. Para cada uma dessas imagens, é gerada uma requisição, que como todas as outras terão de passar pelo nosso RequestProcessor especializado em lidar com permissões.
Esses são os dados técnicos. O problema na prática é o seguinte: quando eu acesso o relatório pela primeira vez tudo ocorre bem, ele abre em 14 segundos, uma beleza para a quantidade de informações que ele carrega - mas quando tento acessá-lo por uma segunda vez, recebo um HTTP 500 quentinho do forno, e de brinde levo um stackTrace falando de OutOfMemoryError.
Eu, muito malandro size=7[/size], fui tentar fazer o debug pra ver o ponto em que costumava carregar mais coisas, e pra minha surpresa, na segunda tentativa o relatório foi gerado com sucesso, junto com as imagens e tudo mais! Insistente size=7[/size] toda vida, tentei fazer o debug pela terceira vez, e nada, continuava tudo funcionando! Quarta, quinta, sexta… É, me senti um pouco, digamos, zoado pelo Java, por assim dizer. Rodei sem o debug depois e lá apareceu o Heap Space todo prosa pra mim!
Pois bem… Com a ajuda de uma MundoJava comecei a desconfiar de sincronização de Threads. O que me intrigava é que o stackTrace sempre me apontava a mesma coisa, que o OutOfMemoryError acontecia sempre no mesmo ponto. E a surpresa… Acontecia na nossa classe que herda de TilesRequestProcessor, em um método específico!
Só pra efeito de teste, resolvi botar um synchronized no método em questão, e tudo funcionou às mil maravilhas. Mas definitivamente não é o que eu quero, não faz o menor sentido querer que uma requesição seja tratada de cada vez. Aí parti pra agressão: “System.gc();” nele! Mas, pensando bem, também não é muito bem o que eu quero, o sistema viraria uma carroça quatro portas! :oops:
Outro teste que fiz, foi botar um System.out.print(String.valueOf(System.currentTimeMillis())); no método onde parece haver o problema de sincronização de Threads, e vi que quando não chamo o GC as duas últimas requisições das imagens passam por ali quase ao mesmo tempo. Quando uso synchronized ou quando chamo o GC, o intervalo entre uma e outra é maior. Algo interessante de se observar, no entanto, é que quando acontece a falta de memória ele não chega a enviar essas duas últimas requisições (sensato, elas são feitas pela JSP, que nem sequer é carregada).
Depois de todas essas observações eu fui na minha aventura de procurar pelo mundo perdido onde todos os programadores dizem encontrar suas soluções, o fórum GUJ… E fica a minha pergunta: tem alguém drogado o suficiente aí com uma possível idéia de solução pro meu problema?
Aguardo respostas, e não hesitem em me pedir mais informações, se necessário.
Agradeço a ajuda de todos, desde já.
Abraços,
Eduardo