리소스 누출 : 'in'은 닫히지 않습니다.


84

Eclipse가 다음 코드에서 "Resource leak : 'in'is never closed"라는 온난화를주는 이유는 무엇입니까?

public void readShapeData() {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();

답변:


69

스캐너를 닫지 않기 때문에

in.close();

39
이렇게하면 Scanner경고 가 닫히고 음소거되지만 System.in일반적으로 바람직하지 않은 경고도 닫힙니다 .
Stuart Cook

@StuartCook +1. 주시해야 할 것.
informatik01

7
스캐너를 닫아야하는 이유는 무엇입니까? "자원 유출"은 무엇을 의미합니까?
Erran Morad 2014 년

1
@nogard :이 답변은 정말 도움이됩니다 ..하지만 in.close (); .. 다시 사용하면 해결할 수 없음을 보여줍니다. 예외 처리없이 코드가 있습니다 .. 감사합니다
pcs

3
@StuartCook, 폐쇄 가 일반적으로 바람직하지 않은 이유 를 언급하는 것을 잊었습니다 System.in. 다시 읽을 수 없기 때문입니다. I. e. 예를 들어 java.util.NoSuchElementException: No line found전화 (new Scanner(System.in)).nextLine()를 시도 하면 얻을 수 있습니다 .
Petr Bodnár 2011

55

다른 사람들이 말했듯이 IO 클래스에서 'close'를 호출해야합니다. 다음과 같이 try-finally 블록을 캐치없이 사용할 수있는 훌륭한 장소라고 추가하겠습니다.

public void readShapeData() throws IOException {
    Scanner in = new Scanner(System.in);
    try {
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();
    } finally {
        in.close();
    }
}

이렇게하면 스캐너가 항상 닫히고 적절한 리소스 정리가 보장됩니다.

마찬가지로 Java 7 이상에서는 "try-with-resources"구문을 사용할 수 있습니다.

try (Scanner in = new Scanner(System.in)) {
    ... 
}

2
리소스 누출은 무엇을 의미하며 나에게 어떤 영향을 미칩니 까?
Erran Morad 2014 년

7
@Borat- "자원 누출"은 일부 시스템 자원 (일반적으로 메모리)이 손실되거나 불필요하게 낭비되고 있음을 의미합니다. 일반적으로 이것은 프로그램이 정상적으로 작동하는 동안 OutOfMemoryErrors가 발생하기 시작할 때 영향을 미칩니다.
Eric Lindauer 2014 년

감사합니다 에릭. 무한 루프에서 문자열을 추가하여 오류를 일으킬 수 있음을 알고 있습니다. 스캐너가 어떻게 그 오류를 일으킬 수 있는지 잘 모르겠습니다.
Erran Morad 2014 년

4
리소스 시도는 어떻습니까?
Dennis Meng 2014

감사합니다 Dennis, 추가.
Eric Lindauer

12

그것이 발생하는지 확인하기 위해 블록 in.close()에서 호출해야 finally합니다.

이클립스 문서에서, 여기에 그 깃발이 특정 문제 ( 강조 광산) :

인터페이스 java.io.Closeable (JDK 1.5 이후) 및 java.lang.AutoCloseable (JDK 1.7 이후 )을 구현하는 클래스 는 더 이상 필요하지 않을 때 close () 메소드를 사용하여 닫아야하는 외부 자원을 나타내는 것으로 간주됩니다.

Eclipse Java 컴파일러는 이러한 유형을 사용하는 코드가이 정책을 준수하는지 여부를 분석 할 수 있습니다.

...

컴파일러는 "Resource leak : 'stream'is never closed"로 [위반] 플래그를 지정합니다.

여기에 자세한 설명이 있습니다 .


7

를 사용하여 인스턴스화 한 스캐너를 닫아야한다는 메시지 System.in입니다 Scanner.close(). 일반적으로 모든 독자는 닫혀 있어야합니다.

을 닫으면 System.in다시 읽을 수 없습니다. Console수업을 살펴볼 수도 있습니다 .

public void readShapeData() {
    Console console = System.console();
    double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: "));
    double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: "));
    ...
}

3
System.console()개발 과정을하는 번거 로움이 될 수있는 이클립스를 통해 응용 프로그램을 실행할 때 사용할 수 없습니다.
Stuart Cook

6

JDK7 또는 8을 사용하는 경우 리소스와 함께 try-catch를 사용할 수 있습니다. 그러면 자동으로 스캐너가 닫힙니다.

try ( Scanner scanner = new Scanner(System.in); )
  {
    System.out.println("Enter the width of the Rectangle: ");
    width = scanner.nextDouble();
    System.out.println("Enter the height of the Rectangle: ");
    height = scanner.nextDouble();
  }
catch(Exception ex)
{
    //exception handling...do something (e.g., print the error message)
    ex.printStackTrace();
}

catch 절은 필수가 아닙니다. 예외가 발생하더라도 리소스가 닫히고 싶지만 OP의 원래 코드 (즉, 전혀 잡히지 try않음)에서와 같이 예외 처리를 그대로 두려면 catch절을 사용하지 않고 표시된대로 사용할 수 있습니다 .
user118967

5
// An InputStream which is typically connected to keyboard input of console programs

Scanner in= new Scanner(System.in);

위의 줄은 System.in 인수를 사용하여 Scanner 클래스의 생성자를 호출하고 새로 생성 된 개체에 대한 참조를 반환합니다.

키보드에 연결된 입력 스트림에 연결되어 있으므로 이제 런타임에 사용자 입력을 받아 필요한 작업을 수행 할 수 있습니다.

//Write piece of code 

메모리 누수를 제거하려면-

in.close();//write at end of code.

4

당신은해야 닫고 당신이 그것을 완료하면 스캐너를 :

in.close();

3

추가 private static Scanner in;하면 문제가 실제로 해결되지 않고 경고 만 지워집니다. 스캐너를 정적으로 만드는 것은 그것이 영원히 열려 있다는 것을 의미합니다 (또는 거의 "영원히"클래스가 언로드 될 때까지). 컴파일러는 "영원히 열어 두십시오"라고 말 했으므로 더 이상 경고를 표시하지 않습니다. 그러나 리소스가 더 이상 필요하지 않으면 즉시 닫아야하므로 실제로 원하는 것이 아닙니다.

HTH, Manfred.


2

일반적으로 I / O를 처리하는 클래스의 인스턴스는 작업을 마친 후에 닫아야합니다. 따라서 코드 끝에 in.close().


2
private static Scanner in;

개인 정적 스캐너 클래스 변수로 선언하여 수정했습니다. 그것이 왜 고쳐 졌는지 확실하지 않지만 그것이 내가 권장하는 일입니다.


5
당신은 경고하지만 생성 된 자원 누출 음소거
zacheusz

1

스캐너를 닫아야합니다. 리소스 및 aovid 메모리 누수를 확보하기 위해 Readers, Streams ... 및 이러한 종류의 개체를 닫는 것이 좋습니다. 그리고 finally 블록에서 그렇게하여 해당 객체를 처리하는 동안 예외가 발생하더라도 닫혀 있는지 확인합니다.


이 답변은 실제로 OP가 그 일을 닫아야하는 이유를 아는 데 도움이됩니다. 물론, 그는 문서를 읽고 " scanner.close()"을 (를) 볼 수 있지만이 답변은 실제로 무슨 일이 일어나고 있는지 이해하는 데 도움이됩니다. + 1
HyperNeutrino

1

좋아요, 진지하게, 적어도 많은 경우에 이것은 실제로 버그입니다. VS Code에도 표시되며 스캐너 개체를 닫지 않고 둘러싸는 범위의 끝에 도달했지만 열려있는 모든 파일 설명자를 닫는 것이 프로세스 종료의 일부라는 것을 인식하지 못하는 것은 linter입니다. 종료시 리소스가 모두 정리되고 프로세스가 사라지고 리소스를 보관할 곳이 없기 때문에 리소스 누수가 없습니다.


0
Scanner sc = new Scanner(System.in);

//do stuff with sc

sc.close();//write at end of code.

-1
in.close();
scannerObject.close(); 

Scanner경고 가 닫히고 종료됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.