2012-09-20 2 views
60

Warum gibt mir Eclipse die Erwärmung "Ressourcenleck: 'in' ist nie geschlossen" im folgenden Code?Ressourcenleck: 'in' ist nie geschlossen

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(); 

Antwort

43

Weil Sie nicht schließen Ihre Scanner

in.close(); 
+28

Dies wird die 'Scanner' schließen und die Warnung zum Schweigen bringen, aber es wird auch in der Nähe' System.in' der in der Regel nicht erwünscht ist. –

+0

@StuartCook +1. Etwas, das man im Auge behalten sollte. – informatik01

+3

Warum müssen wir den Scanner schließen? Was ist mit "Ressourcenlecks" gemeint? –

3

Sie Ihren Scanner close sollten, wenn Sie mit ihm fertig sind:

in.close(); 
2

Allgemeinen Instanzen von Klassen, die mit umgehen I/O sollte geschlossen werden, nachdem Sie mit ihnen fertig sind. Sie können also am Ende Ihres Codes in.close() hinzufügen.

6

Es teilt Ihnen mit, dass Sie den Scanner, den Sie instanziiert haben, unter System.in mit Scanner.close() schließen müssen. Normalerweise sollte jeder Leser geschlossen sein.

Beachten Sie, dass Sie System.in nicht mehr lesen können. Sie können sich auch die Klasse Console ansehen.

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: ")); 
    ... 
} 
+2

Beachten Sie, dass System.console() 'ist nicht verfügbar, wenn eine Anwendung über Eclipse ausgeführt wird, was während der Entwicklung ein Problem darstellen kann. –

0

Der Scanner sollte geschlossen sein. Es empfiehlt sich, Reader, Streams ... und diese Art von Objekten zu schließen, um Ressourcen und Speicherlecks freizugeben. und dies in einem finally-Block zu tun, um sicherzustellen, dass sie geschlossen sind, auch wenn beim Behandeln dieser Objekte eine Ausnahme auftritt.

+0

Diese Antwort hilft OP wirklich zu wissen, warum er das Ding schließen sollte. Sicher, er kann das Dokument lesen und "scanner.close()" sehen, aber diese Antwort hilft ihm wirklich zu verstehen, was vor sich geht. + 1 – HyperNeutrino

36

Wie andere bereits gesagt haben, müssen Sie bei IO-Klassen 'close' aufrufen. Ich werde hinzufügen, dass dies ein ausgezeichneter Ort ist, den Versuch zu nutzen - schließlich ohne Fang blockieren, wie folgt aus:

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(); 
    } 
} 

Dies stellt sicher, dass Ihr Scanner immer geschlossen ist, die richtige Ressource Bereinigung zu gewährleisten.

Gleichwertig in Java 7 oder größer ist, können Sie die "Try-mit-Ressourcen" Syntax:

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

Was ist mit Ressourcenleck gemeint und wie wird es mich betreffen? –

+4

@Borat - "Ressourcenleck" impliziert, dass einige Systemressourcen (normalerweise Speicher) unnötig verloren oder verschwendet werden. In der Regel wirkt sich dies auf Sie aus, wenn Sie OutOfMemoryErrors während des normalen Betriebs Ihres Programms auslösen. –

+0

Danke Eric. Ich weiß, dass Sie den Fehler verursachen können, indem Sie eine Zeichenfolge an sich selbst in einer Endlosschleife anhängen. Ich bin mir nicht sicher, wie ein Scanner diesen Fehler verursachen könnte. –

0
private static Scanner in; 

ich es fest, indem sie als private static Scanner Klassenvariable erklärt in. Nicht sicher, warum das behoben wurde, aber das ist es, was Eclipse mir empfohlen hat.

+2

Sie haben die Warnung stummgeschaltet, aber ein Ressourcenleck erstellt – zacheusz

8

Sie müssen in.close() in einem finally Block aufrufen, um sicherzustellen, dass es auftritt.

Aus der Dokumentation von Eclipse, hier ist warum es Flags dieses besondere Problem (Schwerpunkt von mir):

Klassen die Schnittstelle java.io.Closeable (seit JDK 1.5) Implementierung und java.lang.AutoCloseable (seit JDK 1.7) gelten als externe Ressourcen darstellen, die mit der Methode close() geschlossen werden sollten, wenn sie nicht mehr benötigt werden.

Der Eclipse-Java-Compiler kann analysieren, ob Code, der solche -Typen verwendet, dieser Richtlinie entspricht.

...

Der Compiler-Flag wird [Verletzungen] mit "Ressourcenleck: 'Strom' wird nie geschlossen".

Vollständige Erläuterung here.

1

private static Scanner in; Zugabe nicht wirklich das Problem zu beheben, es löscht nur die Warnung aus. Wenn Sie den Scanner statisch machen, bleibt er für immer offen (oder bis die Klasse entladen ist, was beinahe "für immer" ist). Der Compiler gibt dir keine Warnung mehr, da du ihm gesagt hast "halte es für immer offen". Aber das ist nicht das, was Sie wirklich wollten, da Sie Ressourcen schließen sollten, sobald Sie sie nicht mehr benötigen.

HTH, Manfred.

3

Wenn Sie JDK7 oder 8 verwenden, können Sie try-catch mit Ressourcen verwenden. Dadurch wird der Scanner automatisch geschlossen.

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(); 
} 
0
in.close(); 
scannerObject.close(); 

Es wird Scanner schließen und die Warnung geschlossen.

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

//do stuff with sc 

sc.close();//write at end of code. 
3
// An InputStream which is typically connected to keyboard input of console programs 

Scanner in= new Scanner(System.in); 

über der Linie wird mit dem Argument System.in, Constructor der Klasse Scanner aufrufen und einen Verweis auf neu konstruiertes Objekt zurück.

Es ist mit einem Input Stream verbunden, der Tastatur angeschlossen ist, können Sie dies jetzt zur Laufzeit Benutzereingabe erforderliche Operation zu tun nehmen.

//Write piece of code 

Um den Speicherverlust zu entfernen -

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