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

?
War es hilfreich?

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, PhantomReferences 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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top