Domanda

Abbiamo un'applicazione piuttosto grande e complessa scritta in Java in esecuzione sul pacchetto Gridgain. Il problema che sto riscontrando è che questa applicazione rimarrà lì elaborando le richieste per circa un giorno prima che ogni richiesta inizi a provocare un'eccezione di tipo java.nio.channels.ClosedByInterruptException.

La mia supposizione è che l'applicazione non rilasci handle di file e dopo un giorno di uso continuo si esaurisce e non può più continuare a elaborare le richieste (ogni richiesta richiede la lettura di più file da ciascun nodo della griglia). Abbiamo racchiuso la maggior parte delle operazioni di I / O dei file in classi come questa

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

Penso che il problema sia che questo design non rilascia esplicitamente l'handle del file, la mia soluzione proposta è quella di aggiungere un metodo finalizzato come questo

    protected void finalize() throws Throwable
    {
        reader.close();
        super.finalize();   
    }

che lo farà esplicitamente. La domanda (finalmente) è se questo abbia probabilmente qualche effetto. Classi come java.io.BufferedReader hanno già un meccanismo per affrontare questo tipo di problema?

MODIFICA: Anche qui sarebbe molto apprezzato il modo di verificare se questo è effettivamente il problema ... ovvero c'è un modo per interrogare una JVM in esecuzione e chiedere informazioni sulle allocazioni di handle di file?

È stato utile?

Soluzione

È inutile ignorare finalize () . Se l'handle sta ricevendo la spazzatura raccolta e finalizzata, lo è anche l'istanza di java.io.BufferedReader e verrà chiusa.

È possibile (secondo le specifiche) che l'handle sia stato raccolto, ma non finalizzato, ma ciò non è molto probabile.

Potresti provare a usare PhantomReference per ripulire gli handle di file non utilizzati, ma suppongo che le tue istanze di BufferedReaderImpl siano ancora referenziate da qualche parte (ad es. valori in un < code> Map da nomi di file a handle aperti) e questo è ciò che impedisce loro di essere chiusi (nel qual caso i finalizzatori non aiuteranno.)

Altri suggerimenti

Non è possibile fare affidamento sui finalizzatori per essere chiamati. Non è un buon approccio per la gestione delle risorse. Il costrutto standard in Java per questo è:

InputStream in = null;
try {
  in = ...;
  // do stuff
} catch (IOException e) {
  // error
} finally {
  if (in != null) { try { in.close(); } catch (Exception e) { } }
  in = null;
}

Potresti voler avvolgere questi handle all'interno di una classe, ma questo non è un approccio solido.

Le specifiche Java indicano che non è garantito che ' finalize () ' verrà eseguito. Il tuo codice deve chiudere esplicitamente FileReader tu stesso

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top