Tomcat, memory leak e afins

Sei sei… Vocês devem estar pensando: “mais um tópico sobre a memória no tomcat”…
Mas a idéia é criar uma discussão sobre o que acontece no tomcat. Fiz alguns testes na última semana e constatei alguns fatos que queria dividir com todos…

Vamos lá!

Primeiro: até hoje tenho colocado nossos clientes em hostings como locaweb, e nunca me preocupei em acompanhar o uso de memória e tal. Trabalhava também com outras empresas menores que a locaweb e às vezes tinha problema de queda do tomcat. Também não esquentava muito o côco pra saber exatamente o que seria isso.
Até que recentemente, tomei vergonha na cara e contratei um server próprio pra fazer toda a gerência.
Problema 1: a memória do tomcat. Percebia que fácil fácil o bichinho chegava nos 50%. Foi quando comecei a ler sobre o assunto. Achei bastantes tópicos aqui no GUJ e outros lá fora…
A primeira coisa que pensei foi: ferrei-me! Memory leak.
Baixei o JProfile e comecei minha peregrinação… :lol:
A boa notícia: o sistema em si não tinha problemas. Todos os objetos estavam certinho.
Achei o problema: tenho um servlet que gera os thumbs das imagens de produtos em tempo de execução (on the fly). Apesar de não ter nada de mais no código, os objetos não eram coletados pelo GC.

public void createThumbJAI(String inFilename, OutputStream outStream, int width, int height) throws IOException{
		PlanarImage pi = JAI.create("fileload", inFilename);
		//System.out.println("Largura = " + pi.getWidth());
		//System.out.println("Altura = " + pi.getHeight());
		double newSize = ((double) width) / ((double) pi.getWidth());
		
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(pi);
		pb.add(newSize);
		
		RenderingHints qualityHints = new RenderingHints(
				RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_RENDER_QUALITY);

		//É aplicado o efeito.
		RenderedOp render =  JAI.create("SubsampleAverage", pb, qualityHints);

		/*Como já foi utilizado o ParameterBlock,
		tem que apontar para um novo objeto*/
		//pb = new ParameterBlock();
		//pb.addSource(pi);
		//É informado o local e o nome da nova imagem e o formato.
		//RenderedOp render = JAI.create("fileload", pb);
		ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", outStream, null);
		encoder.encode(render);
	}

Acho que como a imagem é passada direto pro OutputStream, os objetos ficam sendo utilizados.
A solução foi setar null em todas as declarações:

[code]
pi = null;
render = null;
pb = null;
qualityHints = null;
encoder = null;
[/quote]

Se está certo ou não a forma que utilizei eu não sei… Porém, surtiu efeito.

É agora que o trem fica feio e a porca torce o rabo!

Continuei nos testes com o JProfile e vi que agora a memória era liberada.
Só que para minha surpresa o danado do tomcat continuava a usar muita memória. Só para vocês terem idéia da proporção:
Gráfico do JProfiler: 17MB de memória utilizada
Tomcat: 1GB

O tomcat começa normal…
Depois de várias requisições do gerador de thumbs, e vai subindo, subindo…
O GC roda, libera a memória, mas o tomcat em si não…

E aí? Alguém afim de palpitar?