Befreit java Datei-Handles
Frage
Wir haben eine ziemlich große und komplexe Anwendung in Java geschrieben, die auf der Oberseite des Gridgain-Pakets ausgeführt wird. Das Problem, das ich habe, ist, dass diese Anwendung sitzt dort Verarbeitung von Anforderungen für etwa einen Tag vor jeder Anforderung in einer Ausnahme vom Typ java.nio.channels.ClosedByInterruptException resultierenden beginnt.
Meine Vermutung ist, dass die Anwendung nicht Datei-Handles und nach einem Tag Dauerbetrieb ist die Freigabe es zu Ende geht und nicht mehr weiter können Anfragen verarbeiten (jede Anforderung erfordert das Lesen von mehreren Dateien von jedem Gitterknoten). Wir haben die meisten unserer Datei IO-Operationen in Klassen wie diese gewickelt
package com.vlc.edge;
import com.vlc.common.VlcRuntimeException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public final class BufferedReaderImpl implements BufferedReader {
private java.io.BufferedReader reader;
public BufferedReaderImpl(final String source) {
this(new File(source));
}
public BufferedReaderImpl(final File source) {
try {
reader = new java.io.BufferedReader(new FileReader(source));
} catch (FileNotFoundException e) {
throw new VlcRuntimeException(e);
}
}
public BufferedReaderImpl(final Reader reader) {
this.reader = new java.io.BufferedReader(reader);
}
public String readLine() {
try {
return reader.readLine();
} catch (IOException e) {
throw new VlcRuntimeException(e);
}
}
public void close() {
try {
reader.close();
} catch (IOException e) {
throw new VlcRuntimeException(e);
}
}
}
Ich denke, das Problem ist, dass dieser Entwurf explizit die Datei-Handle nicht freigibt, meine vorgeschlagene Lösung ist eine Finalisierung Methode wie folgt
hinzufügen protected void finalize() throws Throwable
{
reader.close();
super.finalize();
}
, die dies ausdrücklich tun. Die Frage (endlich) ist, ob dies wahrscheinlich keine Wirkung haben. Sie Klassen wie java.io.BufferedReader bereits einen Mechanismus haben, um mit dieser Art von Problem zu tun?
EDIT: Auch hier sehr geschätzt Weise wäre zu prüfen, ob dies tatsächlich das Problem ist ... also ist es eine Möglichkeit, eine laufende JVM und fragen Sie es Datei-Handle Zuweisungen abfragen
?Lösung
Es hat wenig Sinn, in übergeordneten finalize()
. Wenn der Griff bekommt Müll gesammelt und fertig gestellt, so ist auch die Instanz von java.io.BufferedReader
und es wird geschlossen erhalten.
Es ist möglich (je nach Spezifikation), dass der Griff Müll gesammelt wird, aber nicht abgeschlossen, aber das ist nicht sehr wahrscheinlich.
Sie könnten versuchen, PhantomReference
s aufzuräumen nicht verwendete Datei-Handles verwenden, aber meine Vermutung ist, dass Ihre Instanzen BufferedReaderImpl
noch von irgendwo (zB Werte in einem Map
aus Dateinamen zu öffnen Griffe) referenziert werden, und das ist, was sie daran hindert, sein geschlossen (in diesem Fall Finalizers wird nicht helfen.)
Andere Tipps
Finalizer kann nicht geltend gemacht werden genannt werden. Es ist kein guter Ansatz für das Ressourcenmanagement. Das Standard-Konstrukt in Java hierfür ist:
InputStream in = null;
try {
in = ...;
// do stuff
} catch (IOException e) {
// error
} finally {
if (in != null) { try { in.close(); } catch (Exception e) { } }
in = null;
}
Sie können diese Griffe in einer Klasse wickeln wollen, aber das ist nicht ein robuster Ansatz.
Java-Spezifikation besagt, dass es nicht garantieren, dass ‚finalize()
‘ ausgeführt wird. Ihr Code muss sich explizit schließen FileReader
.