[RESOLVIDO] Gerenciamento de objetos + Alocação de memória!

Bom dia pessoal,

Estou com o seguinte problema, ontem eu estava com problema na minha aplicação onde uma imagem após ser carregada, estourava a memória da VM.
Então utilizando parametros da VM consegui resolver temporáriamente este problema.

O seguinte problema me ocorre. Quando essa imagem é carregada, executei pelo modo debug pra ver, e segue processo que ela tem:

  1. Cria um um fileChooser e o cara seleciona a imagem;
  2. Ao selecionar a image ele cria um view no fileChooser, ao criar o view no fileChooser ele aloca + 50 mb na memória da aplicação. Até ai tudo bem, pois executando a imagem num navegador ou coisa do tipo ela carrega isto na memória. São imagens grandes de quantidade de pixel, não de tamanho.
  3. Ao selecionar item… ele cria um File e deste File ele cria um ImageIcon…
  4. Deste ImageIcon ele cria um Image implementado no projeto por nós… e neste image segue o codigo que faz:

No local onde diz “AQUIIII” ele alocal mais 100mb na VM, e isso da o break na aplicação se não tiver configurado com os parametros pra VM.

Só que eu quero que a imagem abra com menos alocação de memória, e não que eu passe parametros para alocar mais memória…

E o que acontece é que cria + / - 4 objetos na aplicação enquanto gera esse código! pode ser má lógica no código! E são 4 objetos de imagem…

Se alguem puder me dar uma luz ai… agradeço!!

public void generateThumbnail()
{
    	//create its thumbnail
    	ImageIcon thumbnail = null;
    	ImageIcon thumbnailBig = null;
    	
    	//select scale method
    	int scaleMethod;
    	
    	BufferedImage bufferedImage = null;
    	Graphics2D intersectionGraphics = null;
    	ImageIcon tmpImage = null;
    	
    	//create a new digital image for drawing
    	if(Math.abs(Math.sin(rotation*Math.PI/180))<=1e-5)
    	{
    		bufferedImage = new BufferedImage( 
    	    		digitalImage.getIconWidth(), digitalImage.getIconHeight(), 
    	    		BufferedImage.TYPE_INT_RGB);
    		intersectionGraphics = bufferedImage.createGraphics(); //AQUIIIII
        	tmpImage = new ImageIcon( bufferedImage );
        	AffineTransform tx = new AffineTransform();
        	tx.rotate(rotation*Math.PI/180, digitalImage.getIconWidth()/2, 
            		digitalImage.getIconHeight()/2);
        	intersectionGraphics.drawImage( digitalImage.getImage(), tx, null );
        	        	
    	}
    	else
    	{
    		bufferedImage = new BufferedImage( 
    	    		digitalImage.getIconHeight(), digitalImage.getIconWidth(), 
    	    		BufferedImage.TYPE_INT_RGB);
    		intersectionGraphics = bufferedImage.createGraphics();		
        	tmpImage = new ImageIcon( bufferedImage );
        	AffineTransform tx = new AffineTransform();
            tx.rotate(rotation*Math.PI/180, 0, 0);
            if(Math.sin(rotation*Math.PI/180) > 0)
            {
            	tx.translate(0,-digitalImage.getIconHeight());
            }
            else
            {
            	tx.translate(-digitalImage.getIconWidth(),0);
            }
            intersectionGraphics.drawImage( digitalImage.getImage(), tx, null );
                    	
    	}
    	
 /*   	Graphics2D intersectionGraphics = bufferedImage.createGraphics();		
    	ImageIcon tmpImage = new ImageIcon( bufferedImage );
    	
    	AffineTransform tx = new AffineTransform();
        tx.rotate(rotation*Math.PI/180, digitalImage.getIconWidth()/2, 
        		digitalImage.getIconHeight()/2);
        
        intersectionGraphics.drawImage( digitalImage.getImage(), tx, null );*/
        
    	//draw digital image
  	/*intersectionGraphics.drawImage( digitalImage.getImage(), 0, 0, 
        	digitalImage.getIconWidth(), 
        	digitalImage.getIconHeight(), null );*/
    	
      //draw all elements
    	
    	for(Iterator<AbstractGraphic> it = graphics.iterator(); it.hasNext();){
        //paint graphic on this graphical context
    	  it.next().paint(intersectionGraphics, 1);
    	}

    	//check extension
    	if( fileName.indexOf(".gif") > 0 )
    	{
    		//scale gif with default method
    		//it also works with animated gifs
    		scaleMethod = java.awt.Image.SCALE_DEFAULT;
    	}
    	else
    	{
    		//scale everything else with smooth scale
    		scaleMethod = java.awt.Image.SCALE_SMOOTH;
    	}
    	    	
    	//check image aspect
    	if( ((float)tmpImage.getIconHeight()) / 
    		((float)tmpImage.getIconWidth() ) 
    		<= 0.75 )
    	{
    		//image is wide
    		//check width
    		if( tmpImage.getIconWidth() > Image.THUMBNAILWIDTH )
    		{
            	//rescale image
            	thumbnail = new ImageIcon(
            			tmpImage.getImage().getScaledInstance(
            			Image.THUMBNAILWIDTH, -1, scaleMethod ));
            	thumbnailBig = new ImageIcon(
            			tmpImage.getImage().getScaledInstance(
            			Image.THUMBNAILWIDTHBIG, -1, scaleMethod ));
            	
            	
    		}
    		else
    		{
    			//no need to rescale image
    			thumbnail = new ImageIcon( tmpImage.getImage() );
    			thumbnailBig = new ImageIcon( tmpImage.getImage() );
    			
    		}
    	}
    	else
    	{
    		//image is tall
    		//check height
    		if( digitalImage.getIconHeight() > Image.THUMBNAILHEIGHT )
    		{
            	//rescale image
            	thumbnail = new ImageIcon(
            			tmpImage.getImage().getScaledInstance(
            			-1, Image.THUMBNAILHEIGHT, scaleMethod) );
            	thumbnailBig = new ImageIcon(
            			tmpImage.getImage().getScaledInstance(
            			-1, Image.THUMBNAILHEIGHTBIG, scaleMethod) );
    		}
    		else
    		{
    			//no need to rescale image
    			thumbnail = new ImageIcon( digitalImage.getImage() );
    			thumbnailBig = new ImageIcon( digitalImage.getImage() );
    			
    		}
    	}
    	
    	//set thumbnail
    	setThumbnail( thumbnail );
    	setThumbnailBig( thumbnailBig );
}

Imagem com grande quantidade de pixel e não de tamanho? Como assim?

Toda imagem tem que ser carregada na memória, não há outro jeito.

Ahh…é o mesmo do outro post. Deu pra ver pelo código.

Me explica uma coisa. O objeto AffineTransform é para girar o objeto em 180º?
Tenho a ligeira impressão que o seu problema está ae.

Por que você não carrega a imagem com ImageIO?
Você está criando um Graphics2D na pilha do windows, com largura e altura, de certo muito grandes.
Sabe que a pilha do windows suporta apenas 8mb?

Vai ter que alocar esse recurso em outra área da memória.

http://www.maxi-pedia.com/what+is+heap+and+stack

E qual é o problema de pedir para sua VM usar mais memória? Você vai ter imagens maiores que isso?

Anyway, na linha de cima do código do AQUIIIIII, você cria um novo BufferedImage. Esse BufferedImage tem as mesmas dimensões do original, ou seja, você fica com 2x a imagem carregada nos icons na memória. Se sua intenção é só girar a imagem, talvez seja melhor você fazer um método de pintura que simplesmente rotacione o sistema de coordenadas antes de pintar a imagem. Isso evitará uma cópia em memória, fazendo a rotação só ocorrer no buffer de pintura.

Aliás, pare de usar o ImageIcon, e passe a carregar imagens diretamente, através do ImageIO.

[quote=juliocbq]Imagem com grande quantidade de pixel e não de tamanho? Como assim?

Toda imagem tem que ser carregada na memória, não há outro jeito.

Ahh…é o mesmo do outro post. Deu pra ver pelo código.

Me explica uma coisa. O objeto AffineTransform é para girar o objeto em 180º?
Tenho a ligeira impressão que o seu problema está ae.[/quote]

Não sei muito quanto a quantidade de pixel ou o tamanho…
tentamos imaginar que a imagem tem 1 mb porque não é aceitavel mais de 2 mb na aplicação…

e essa imagem de 1 mb gera 150 mb na aplicação… é valido?

Acho que não deveria acontecer isso
:frowning:

[quote=juliocbq]Por que você não carrega a imagem com ImageIO?
Você está criando um Graphics2D na pilha do windows, com largura e altura, de certo muito grandes.
Sabe que a pilha do windows suporta apenas 8mb?

Vai ter que alocar esse recurso em outra área da memória.

http://www.maxi-pedia.com/what+is+heap+and+stack[/quote]

Não carrego a imagem no ImageIO porque eu entrei na empresa agora e não posso sair alterando o código afu!

é bem conversado para não afetar outras coisas…

Sla… não entendi muito bem…!! e não sabia que a pilha do windows suporta só 8mb…

Vou dar uma olhada no link!!
:smiley:

[quote=ViniGodoy]E qual é o problema de pedir para sua VM usar mais memória? Você vai ter imagens maiores que isso?

Anyway, na linha de cima do código do AQUIIIIII, você cria um novo BufferedImage. Esse BufferedImage tem as mesmas dimensões do original, ou seja, você fica com 2x a imagem carregada nos icons na memória. Se sua intenção é só girar a imagem, talvez seja melhor você fazer um método de pintura que simplesmente rotacione o sistema de coordenadas antes de pintar a imagem. Isso evitará uma cópia em memória, fazendo a rotação só ocorrer no buffer de pintura.

Aliás, pare de usar o ImageIcon, e passe a carregar imagens diretamente, através do ImageIO. [/quote]

O problema de pedir pra VM usar mais memória é o seguinte:

Digamos que nesse local onde vem 1 image! por ter 1 ou 10… se cada vez que eu adiciono 2 image ele pula 100 mb… tenta imaginar 10?! meio que travaria pc!
É um local onde pode se coloca diversas imagens…

E se por esse ImageIO não der? pois os caras querem que seja desse jeito?!
Não tem um jeito mais facil de resolver esse problema utilizando apenas o que tens em mãos?
Hehe :smiley:

Seria mais util eu colocar o código que faz isso pra vocês? as partes importantes das classes ? :smiley:

[quote=“jonathanprogrammer”]Digamos que nesse local onde vem 1 image! por ter 1 ou 10… se cada vez que eu adiciono 2 image ele pula 100 mb… tenta imaginar 10?! meio que travaria pc!
É um local onde pode se coloca diversas imagens…
[/quote]

Se você for processar uma imagem por vez, esse problema que você está descrevendo não existirá, a menos que você fique guardando referências das imagens num array/list.

Se você carrega mesmo todas as imagens desse local, então, um dia esse problema acontecerá, seja lá qual for o tamanho da imagem, ou do heap.

Vamos ver se eu entendi. Você quer resolver o problema, mas não pode alterar o programa?
Nesse caso… talvez seja melhor apelar para magia, cartomancia, tarologia, ou qualquer outra arte mística…

Entenda uma coisa. No disco uma imagem está num formato compactado. Sim, formatos como png, jpg ou gif tem compactação. Só tem esses nomes pq essa compactação é diferente do “.zip”, já que é própria para imagens. Para essa imagem ser manipulada, seja pelo java ou pela placa de vídeo, ela precisa ser descompactada.

Faça o seguinte, abra sua imagem no photoshop/gimp ou qualquer outro editor que queira, e salve-a no formato .bmp. Veja o tamanho resultante. Esse tamanho será próximo do que você terá no vídeo ou na aplicação.

Agora, sua imagem é criada pelo menos 3 vezes em sua aplicação:
a) Você carrega ela dentro do image icon;
b) Você faz uma versão rotacionada da imagem;
c) Você coloca a imagem num JFrame, que vai ocupar memória de vídeo.

Então, sim, é possível que uma imagem grande esteja ocupando 150mb da memória. Uma das formas de resolver isso, seria você criar seu próprio componente que exibe imagens. Isso poderia evitar o passo B, já que ele poderia desenhar na memória de vídeo a imagem já rotacionada. E isso não é difícil de fazer.

No caso do stack, não se preocupe. Todos os objetos em java são carregados no heap. Entretanto, o heap máximo da VM padrão é só de 64mb, o que pode ser realmente bem limitado para uma aplicação que manipule imagens das dimensões que você manipula.

Você precisa é dimensionar o pico da sua aplicação, e definir o seu stack para suportar esse pico. E provavelmente, será maior do que 100mb. A maior parte das máquinas pode ter aplicações usando mais do que isso em memória.

Da outra vez que fiz isso (ficar respeitando um código abandonado por outra pessoa na empresa, que não estava lá para dar manutenção, só porque “não pode sair alterando o código”) eu me arrependi amargamente. Decidi depois disso que é melhor SEMPRE falar com o chefe para ver o que deve ser feito, e se houver algum problema arquitetural que exija que o código anterior seja jogado fora, pedir a permissão para poder mexer e fazer as coisas do jeito que têm de ser feitas.).

É muito mais difícil mexer só um pouco e fazer funcionar (isso exige bastante experiência!) que mexer bastante e fazer funcionar. No seu caso, que você não parece ser muito experiente, então é melhor falar com seu chefe.

ouça o que o pessoal disse. Carregue a imagem uma vez, e aplique a transformação na mesma imagem.l

[quote=ViniGodoy]
Entenda uma coisa. No disco uma imagem está num formato compactado. Sim, formatos como png, jpg ou gif tem compactação. Só tem esses nomes pq essa compactação é diferente do “.zip”, já que é própria para imagens. Para essa imagem ser manipulada, seja pelo java ou pela placa de vídeo, ela precisa ser descompactada.

Faça o seguinte, abra sua imagem no photoshop/gimp ou qualquer outro editor que queira, e salve-a no formato .bmp. Veja o tamanho resultante. Esse tamanho será próximo do que você terá no vídeo ou na aplicação.

Agora, sua imagem é criada pelo menos 3 vezes em sua aplicação:
a) Você carrega ela dentro do image icon;
b) Você faz uma versão rotacionada da imagem;
c) Você coloca a imagem num JFrame, que vai ocupar memória de vídeo.

Então, sim, é possível que uma imagem grande esteja ocupando 150mb da memória. Uma das formas de resolver isso, seria você criar seu próprio componente que exibe imagens. Isso poderia evitar o passo B, já que ele poderia desenhar na memória de vídeo a imagem já rotacionada. E isso não é difícil de fazer.

No caso do stack, não se preocupe. Todos os objetos em java são carregados no heap. Entretanto, o heap máximo da VM padrão é só de 64mb, o que pode ser realmente bem limitado para uma aplicação que manipule imagens das dimensões que você manipula.

Você precisa é dimensionar o pico da sua aplicação, e definir o seu stack para suportar esse pico. E provavelmente, será maior do que 100mb. A maior parte das máquinas pode ter aplicações usando mais do que isso em memória.[/quote]

Cara, tu não teria alguma aplicação de exemplo pra me passar?

Pra dar uma olhada… até tava conversando com meu chefe como o cara comento ali embaixo… e a idéia é resolve, mesmo que altere o código…

Mas não to tão afinado assim eu acho pra já sair tocando… precisava ver um exemplo, sla…
:?

Hmm… sim… eu vou fazer isso!!

Tu falou no outro tópico que tu ja trabalhava com isso direto!!

Tu tens um exemplo ai pra me mandar? pra dar uma olhada ou só o código mesmo?

Valeu jow!
:smiley:

Hmm… sim… eu vou fazer isso!!

Tu falou no outro tópico que tu ja trabalhava com isso direto!!

Tu tens um exemplo ai pra me mandar? pra dar uma olhada ou só o código mesmo?

Valeu jow!
:smiley: [/quote]

http://homepages.inf.ed.ac.uk/rbf/HIPR2/wksheets.htm

Hmm… sim… eu vou fazer isso!!

Tu falou no outro tópico que tu ja trabalhava com isso direto!!

Tu tens um exemplo ai pra me mandar? pra dar uma olhada ou só o código mesmo?

Valeu jow!
:smiley: [/quote]

http://homepages.inf.ed.ac.uk/rbf/HIPR2/wksheets.htm[/quote]

Exemplo linha de código!? :?

Hmm… sim… eu vou fazer isso!!

Tu falou no outro tópico que tu ja trabalhava com isso direto!!

Tu tens um exemplo ai pra me mandar? pra dar uma olhada ou só o código mesmo?

Valeu jow!
:smiley: [/quote]

http://homepages.inf.ed.ac.uk/rbf/HIPR2/wksheets.htm[/quote]

Exemplo linha de código!? :? [/quote]

sem querer ser chato, mas você é muito preguiçoso. No link que te passei tem vários exemplos com código fonte java.

Valeu a ajuda… problema resolvido!