Was passiert mit einem BufferedReader, der nicht innerhalb einer callable.call geschlossen wird?

8

Ich habe drei Fragen.

Um das zu erklären, habe ich den Code von jemandem überprüft und festgestellt, dass BufferedReader s manchmal nicht geschlossen wird. Normalerweise gibt Eclipse eine Warnung, dass dies ein potenzieller Speicherverlust ist (und ich repariere es). Innerhalb einer Callable-internen Klasse gibt es jedoch keine Warnung.

%Vor%

Die Leute, die den Code geschrieben haben, sind erfahrene Java-Entwickler, also mein erster Gedanke ist, dass es beabsichtigt ist ... aber es könnte sein, dass sie es eilig hatten, wenn sie es geschrieben haben und es einfach übersehen haben.

Meine Fragen sind:

  1. Warum hebt Eclipse dies nicht hervor (was durch die Antwort auf die folgenden Fragen beantwortet werden kann)?

  2. Was ist das Schlimmste, das passieren könnte, wenn es innerhalb der call () Methode geschlossen wird? (Ich kann mir keinen guten Grund vorstellen ... und ich habe eine Weile gesucht ... aber vielleicht war es beabsichtigt, den BufferedReader nicht zu schließen)

  3. Was ist das Schlimmste, das passieren kann, wenn der BufferedReader nicht in der inneren Klasse geschlossen ist?

GLaDOS 30.08.2012, 18:33
quelle

5 Antworten

6

Ich würde sagen, dass, da sie eine BufferedReader um eine gegebene InputStream herum erstellen, der Code sicher nicht close() aufruft. Der Code, der close() aufruft, sollte immer der Code sein, der den Stream erstellt und mit try / finally erledigt.

%Vor%

Noch ein Hinweis: Ihr Code scheint die Ausgabe von einem anderen Prozess zu protokollieren. Sie könnten den Stream wahrscheinlich sowieso nicht schließen. Ohne es selbst zu testen, bin ich nicht sicher, was passieren würde, wenn Sie einen Stream von einem anderen Prozess schlossen.

Oh, und das IOException tritt wahrscheinlich nicht auf, weil der Stream von einem anderen Prozess kommt. Dies ist wahrscheinlich nur dann der Fall, wenn ein nicht behebbarer Fehler auftritt. Es wäre aber trotzdem keine schlechte Idee, die Ausnahme irgendwie zu protokollieren.

Bearbeiten, um Ihren Kommentar zu gemischten Antworten zu beantworten:

Verwenden wir einen Ausgabestream und BufferedWriter als Beispiel dieses Mal: ​​

%Vor%

Das funktioniert. Die Methode writeLine wird als Stellvertreter zum Erstellen von writer und zum tatsächlichen Schreiben eines einzelnen line in die Datei verwendet. Natürlich könnte diese Logik etwas komplexer sein, wie zum Beispiel ein Objekt in ein String zu verwandeln und es zu schreiben. Dies macht die main -Methode ein wenig einfacher zu lesen.

Was nun, wenn wir statt dessen den BufferedWriter geschlossen haben?

%Vor%

Versuchen Sie es damit auszuführen, und es wird jedes Mal beim zweiten writeLine Aufruf fehlschlagen. Es empfiehlt sich, Streams immer an der Stelle zu schließen, an der sie erstellt wurden, anstatt an der Stelle, an der sie übergeben wurden. Am Anfang mag es in Ordnung sein, aber dann könnte der Versuch, diesen Code später zu ändern, zu Fehlern führen. Wenn ich mit nur 1 writeLine call mit der bad-Methode gestartet habe und jemand anderes eine zweite hinzufügen wollte, müsste der Code umgestaltet werden, damit writeLine den Stream trotzdem nicht schließt. Nahezu glücklich zu werden, kann Kopfschmerzen auf der Straße verursachen.

Beachten Sie auch, dass das BufferedWriter nicht das eigentliche Handle für Ihre Systemressource ist, sondern das FileOutputStream . Daher sollten Sie die tatsächliche Ressource trotzdem schließen.

Also, Faustregel: Schließen Sie nur Ihre Streams, wo Sie sie erstellen, und machen Sie immer die Erstellung und das Schließen in einem try / finally-Block (oder Java 7's großartig try/resource block , was das Closing für Sie erledigt.

    
Brian 30.08.2012, 18:50
quelle
1

BuffereddReader close ()

  

Schließt diesen Stream und gibt alle zugeordneten Systemressourcen frei   es. Wenn der Stream bereits geschlossen ist, hat das Aufrufen dieser Methode keine   Wirkung.

Wenn Sie also nicht schließen (), können Systemressourcen immer noch mit dem Reader verbunden sein, was zu einem Speicherleck führen kann.

Warum Eclipse nicht Hervorhebung: Es ist kein Fehler bei der Kompilierung, wenn Sie den Aufruf von close () ignorieren, damit Eclipse nicht hervorgehoben wird.

    
kosa 30.08.2012 18:38
quelle
1

Sie möchten möglicherweise in diesem Fall BufferedReader nicht schließen. Das InputStream , das an den Konstruktor übergeben wurde, ist das Objekt, das einer Systemressource zugeordnet sein kann. Die BufferedReader und die InputStreamReader sind nur Wrapper dafür. Das Schließen von BufferedReader würde auch den InputStream schließen, was möglicherweise nicht das ist, was der Aufrufer wollte.

    
Kenster 30.08.2012 18:53
quelle
1
  1. Hervorhebung nicht und stimmt, weil ein Stream an einer anderen Stelle als der Aufrufmethode geschlossen werden kann.

  2. Wenn es innerhalb der Aufrufmethode geschlossen wird, können andere Threads es momentan verwenden.

  3. Mit BufferdRreader nichts als, wenn Sie den Verweis auf den Stream verlieren und ihn nicht schließen können und dies zu einem Speicherverlust führt.

Roman C 30.08.2012 18:56
quelle
1

Egal wo du den Stream öffnest, du solltest ihn im finally Block schließen und es ist eine gute Übung den Stream auch für null zu testen, denn wenn die Datei nicht existiert ist der Stream null , Ausnahme wird geworfen ( FileNotFoundException ), aber der finale Bock ist fertig. I.e. Der Inhalt der Aufrufmethode sollte lauten:

%Vor%

Oder wenn Sie Java 7 verwenden dürfen, können Sie die Vorteile von AutoCloseable interface und die neue Sprachstruktur für diesen Zweck nutzen.  siehe Ссылка

    
Jiri Kremser 30.08.2012 18:51
quelle