2015-10-22 15 views
7

Vorrei sapere quando chiude un flusso se non è chiuso manualmente. Con questo voglio dire, il flusso sarà chiuso se lo scopo del suo riferimento non è più?Quando chiude un flusso se non viene chiuso manualmente?

Considerare il seguente scenario di esempio.

Class A{ 
InputStream in; 
OutputStream out; 
A(){ 
    // Initialize and create the streams. 
} 
... 
} 
Class B{ 
public void myMethod(){ 
A a = new A(); 
System.out.println("End of my method.") 
} 
... 
} 

Qui, una volta che mi sono fatto con il flusso, sto uscendo myMethod() ma il programma che a sua volta il processo, non è terminato e prosegue con altre operazioni.

Non ho chiuso i flussi. Si chiuderà automaticamente una volta terminato lo scopo del riferimento alla classe A? (ad esempio, quando termina myMethod())? GC si prende cura di questo? Inoltre, ho letto che gli stream verranno chiusi una volta che il processo è terminato e il sistema rilascia tutte le risorse a disposizione per altri processi. Come possiamo verificare se lo stream è aperto o no? Ci sono dei comandi o opzioni linux da Java per verificarlo?

Qualsiasi aiuto è apprezzato!

+0

Come regola, è necessario chiudere sempre tutti gli stream (e Closeables in generale) in un blocco 'finally' (o provare con risorse) –

+0

A questo punto, mi siedo sulla sedia, e sto provando per ricordare tutti i flussi Java che ho aperto e presumo che abbiano chiuso automaticamente fuori dal campo di applicazione. Per gli ultimi 15 anni. Poi, mi alzo e urlo "C++ ti amo così tanto". – Chameleon

risposta

10

Non credo che le specifiche JVM ne garantiscano alcuna. Si suppone che si debbano veramente pagare le risorse a finally.

Al termine del processo, il sistema operativo rilascia tutte le risorse ad esso associate (inclusi memoria, handle di file e socket di rete).

Esistono strutture del sistema operativo per controllare i file aperti e gli stream, ad esempio lsof.

+1

Sì, lo sto chiudendo in un blocco 'finally', ma chiesto per curiosità. Ma non pensi che GC dovrebbe essere configurato per occuparsi anche di questo? Perché, una volta terminata la portata di un riferimento, tutti i flussi a cui fa riferimento insieme alla memoria devono essere sottoposti a garbage collection. Non è vero? –

+0

Sì, il GC alla fine si verificherà. Ma non è garantito che sia tempestivo, e non è completamente garantito l'esecuzione del finalizzatore (che chiuderebbe il flusso). La posizione è che lo sviluppatore dovrebbe prendersene cura. – Thilo

0

Questa è una cattiva pratica di programmazione, un errore dal programmatore. A seconda dell'origine dati sottostante, potrebbe non chiudersi mai e si possono avere perdite. DEVI chiudere tutte le risorse quando hai finito con questo, in un blocco finally, o usando un tentativo con risorse se Java 7 o superiore, per assicurarti che sia chiuso anche se viene lanciata un'eccezione.

InputStream in; 
OutputStream out; 
try { 
    // Do your stuff with the streams 
} finally { 
    if (in != null) { 
     in.close(); 
    } 
    if (out != null) { 
     out.close(); 
    } 
} 
4

Se non si clossing manualmente allora tutte le risorse non gestite verrà rilasciato quando i termiantes processo, tuttavia non è un o di una pratica migliore consigliato. Dovresti sempre chiudere il tuo stream una volta che hai finito.

Un modo migliore e ha suggerito di gestire il flusso è quello di utilizzare l'opzione provare risorsa come questo con:

try (InputStream input = new FileInputStream(...); 
    Reader reader = new InputStreamReader(input, ...)) { 
    ... 
} 

non ho chiuso i flussi. Si chiuderà automaticamente una volta terminato lo scope del riferimento alla classe A?

No, non si chiuderà automaticamente.

Un buon riferimento da seguire è:

Better Resource Management with Java SE 7: Beyond Syntactic Sugar

2

Nel caso di FileInputStream c'è un metodo finalize() che libererà risorse quando il flusso è garbage collection.

Non si può o si deve fare affidamento su quello. È proprio quello che fa FileInputStream.SocketInputStream sostituisce invece finalize() per fare esplicitamente nulla, basandosi su Socket per chiudere le risorse (e Socket non ha un metodo finalize()).

0

Con Java 7, è possibile creare una o più "risorse" nell'istruzione try. Una "risorsa" è qualcosa che implementa l'interfaccia java.lang.AutoCloseable. Questa risorsa verrebbe automaticamente chiusa e la fine del blocco try.

si può guardare this e java doc per ulteriori informazioni

printFileJava7 static void privato() throws IOException {

try(FileInputStream input = new FileInputStream("file.txt")) { 

    int data = input.read(); 
    while(data != -1){ 
     System.out.print((char) data); 
     data = input.read(); 
    } 
} 

}

Quando il blocco try termina la FileInputStream verrà chiusa automaticamente. Ciò è possibile perché FileInputStream implementa l'interfaccia Java java.lang.AutoCloseable. Tutte le classi che implementano questa interfaccia possono essere utilizzate all'interno del costrutto try-with-resources.

1

Non vi è garanzia che le risorse vengano chiuse finché la JVM è in esecuzione, l'implementazione suggerita è piuttosto pericolosa.

Cosa vorrei suggerire. Rendi la classe A chiudibile e utilizza la dichiarazione tryResourceClose di Java. L'esempio è qui. https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

Dopo aver lasciato il blocco try si ha la possibilità di chiudere le risorse.

Lo stream stesso normalmente non sa se è aperto o meno. Tuttavia, la tua classe A può tenerla traccia degli stream chiusi o meno.

Problemi correlati