2017-08-02 6 views
1

J'ai trouvé plusieurs questions similaires, mais je n'arrive toujours pas à trouver la réponse à ma question.Est-ce que Inline est créé InputStream fermé automatiquement par GC?

Je sais qu'il suffit de fermer le flux externe et qu'il va fermer le flux interne qui est créé en ligne.

BufferedInputStream br = new BufferedInputStream(new FileInputStream(file)); 
br.close(); 

Tenir compte exemple suivant

Properties props = new Properties(); 
props.load(new FileInputStream(configPath)); 

Si le FileInputStream être affecté à une variable puis fermée explicitement (ou à la construction essayer avec des ressources) ou sera Java GC fermer automatiquement juste après props.load() méthode invocation, car il n'y a pas de référence à la ressource?

+1

Qu'entendez-vous par 'GB'? – biziclop

+1

Vous ne devriez pas compter sur garbage collector pour faire la libération des ressources. La réponse correcte à votre question est "_it pourrait, ou pourrait ne pas". –

+0

Pour approfondir le commentaire de @ M.Prokhorov: il n'y a aucune garantie quand le garbage collector fera son travail, en principe il peut retarder son travail indéfiniment, ce qui signifie que la ressource restera allouée indéfiniment, ce qui n'est pas ce que vous voulez. Fermez les ressources explicitement au lieu de vous fier au GC. – Jesper

Répondre

6

Le Javadoc indique que

Le flux spécifié reste ouvert après cette méthode est retournée.

Alors oui, vous devriez le fermer vous-même si vous voulez écrire du code propre. Le GC va le fermer finalement, si il se déplace pour appeler la méthode finalize() (montrée ci-dessous) sur le flux, mais vous shouldn't rely on that.

Toujours fermer vos ressources, c'est la seule façon d'être sûr.

/** 
* Ensures that the <code>close</code> method of this file input stream is 
* called when there are no more references to it. 
* 
* @exception IOException if an I/O error occurs. 
* @see  java.io.FileInputStream#close() 
*/ 
protected void finalize() throws IOException { 
    if ((fd != null) && (fd != FileDescriptor.in)) { 
     /* if fd is shared, the references in FileDescriptor 
     * will ensure that finalizer is only called when 
     * safe to do so. All references using the fd have 
     * become unreachable. We can call close() 
     */ 
     close(); 
    } 
} 
3

Il faut souligner que l'utilisation du code comme

BufferedInputStream br = new BufferedInputStream(new FileInputStream(file)); 
// you likely insert actual operations on br here 
br.close(); 

est fortement déconseillée, car la fermeture ne se produira pas, si une opération entre la construction de cours d'eau et l'appel close() lance une exception.

Vous devez utiliser le « essayer de ressource » construire à la place:

try(BufferedInputStream br = new BufferedInputStream(new FileInputStream(file))) { 
    // your actual operations on br here 
} 

Cela garantit que close() sera appelée même si une exception se produit dans le corps try. Cependant, ce code repose sur le fait connu que la méthode close() de BufferedInputStream appellera la méthode close() de FileInputStream, mais cela n'arrivera que lorsque la construction du BufferedInputStream aura été complétée. Si le constructeur BufferedInputStream lève une exception, sa méthode close() ne sera pas appelée, car il n'y a aucun objet à appeler close().

Une solution vraiment sûre est

try(FileInputStream fis = new FileInputStream(file); 
    BufferedInputStream br = new BufferedInputStream(fis)) { 
    // your actual operations on br here 
} 

qui ferme la FileInputStream même si le constructeur de BufferedInputStream lance une exception. Cela pourrait ressembler à un cas de coin rare ici, car la seule chose qui peut mal tourner dans ce constructeur serait l'allocation de tampon qui pourrait lancer un OutOfMemoryError et vous êtes dans le pétrin de toute façon dans ce cas.

Mais considérez un exemple comme

try(FileInputStream fis = new FileInputStream(file); 
    ObjectInputStream ois = new ObjectInputStream(fis)) { 
    // your actual operations on ois here 
} 

Depuis le constructeur de ObjectInputStream lit déjà l'en-tête, IOException s peuvent être jetés, aussi, l'en-tête peut être invalide, ce qui entraînerait aussi une exception. Par conséquent, il ya beaucoup plus qui peut mal tourner et s'assurer que le FileInputStream sous-jacent est correctement fermé, même dans ces cas est beaucoup plus important.