Resource leak

6 respostas
G

Bom, eu ao tentar resolver um problema no meu eclipse, acabei meio que danificando ele. Com isso, eu reinstalei o eclipse, e comecei a passar meus arquivos da minha antiga workspace (manualmente por sinal).
Só que a versão do eclipse que eu baixei parece ser mais nova que a passada, e quando eu copiei um código de uma classe que eu havia criado e estava sem nenhum erro na versao passada do eclipse, agora possui esse erro:
Resource leak: ‘input’ never closed.

Aqui o código:

import java.util.Scanner;

public class Caixa {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int escolha, lado, aux,aux2;
		
		System.out.println("MENU");
		System.out.println("1 - Caixa cheia");
		System.out.println("2 - Caixa vazia");
		System.out.print("Escolha: ");
		escolha = input.nextInt();
		
		if (escolha == 1){
			System.out.print("Tamanho dos lados: ");
			lado = input.nextInt();
			aux2 = lado;
			
			while (lado > 0){
				System.out.print("\n");
				aux = aux2;
				while (aux > 0){
					System.out.print("*");
					aux--;
				}	
				lado--;
			}
			
		}

		if (escolha == 2){
			System.out.print("Tamanho dos lados: ");
			lado = input.nextInt();
			aux2 = lado;
			
			while (lado > 0){
				System.out.print("\n"); //Para mudar de linha!!!
				aux = aux2;  // aux2 será usado de referencia para saber tamanho do lado
				if (lado != aux2 && lado != 1){ //Se não for nem o primeiro nem a ultima linha
					while (aux > 0){
						if (aux == aux2 || aux == 1){ // Se for a primeira ou ultima posição
							System.out.print("*");
						}
						else {
							System.out.print(" ");  //Se forem outras posições
						}
						aux--;					//Diminui um de aux
					}
				}
				else {					//Se for a primeira ou ultima linha
					while (aux > 0){	
						System.out.print("*"); //Preencherá a linha de "*"
						aux--;
					}
				}
				lado--;                       //Diminui 1 de lado
			}
			
			
		}
		
		
	}

}

Pesquisando pela net vi que se por “input.close();” resolveria. Eu pus e realmente resolveu.
Mas queria saber o que mudou da versão passada para essa nova que gerou esse erro. É uma melhoria? Quero dizer, acredito que isso sirva pra evitar desperdicio de memória ou algo assim.
Mas só preciso que me expliquem melhor o erro e as mudanças dessa versão do eclipse.

6 Respostas

Hebert_Coelho

Não sei se isso seria coisa do eclipse ou da JDK, mas posso dizer uma coisa: utilize try/finaly em recursos que necessitam ser fechados. Se acontecer alguma exception ai o close não será chamado.

Memory Leak é quando o recurso está aberto e você não o fecha. Isso é problema grave que já vi derrubar projetos enormes.

G

Eu queria uma explicação mais detalhada sobre o erro em si… Mas obrigado!

gomesrod

É isso que o Hebert falou, sem o close() você corre o risco de não encerrar os recursos (memória, arquivo, conexões, …) e causar grander problemas.

Provavelmente o que aconteceu no seu caso é que na nova versão o compilador ficou mais “esperto” para detectar essa situação e emitir um aviso, o que não acontecia na versão anterior.

gomesrod

Só por curiosidade:

Fiz um teste aqui:

public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		String line = s.nextLine();
		System.out.println("Typed: " + line);
	}

Ao compilar esse código com JDK7 acontece o warning “Resource Leak: s is never closed”. Mudando para JDK6 o mesmo não acontece, o o código compila sem nenhum aviso.

Outra coisa interessante: se eu passar o objeto como parâmetro para um método, assim:

public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		String line = s.nextLine();
		System.out.println("Typed: " + line);
		doNothing(s);
	}

private static void doNothing(Scanner s) {
		
	}

O warning também desaparece. Provavelmente porque o método poderia ter um s.close() dentro dele, mas o compilador não tem como rastrear e por via das dúvidas retira o warning.

G

Obrigado Gomesrod… Deu pra entender esclarecer um pouco mais… Só que eu não mudei de JDK, apenas baixei um eclipse mais novo.

ViniGodoy

Se for com o Java 7, ele está dando o warning porque a classe implementa a interface AutoCloseable. Portanto, o correto é utilizar o try with resources para garantir que o Scanner será fechado ao final do processo:

public static void main(String[] args) { try (Scanner s = new Scanner(System.in)) { String line = s.nextLine(); System.out.println("Typed: " + line); } }

Ironicamente, não faz sentido dar close em algo que usar o System.in. Mas como o Scanner pode conter outros tipos de InputStream em seu interior, o compilador não tem como saber disso para evitar o warning.

Criado 3 de janeiro de 2014
Ultima resposta 7 de jan. de 2014
Respostas 6
Participantes 4