2017-08-02 162 views
1

我發現了幾個類似的問題,但我仍然無法找到我的問題的答案。內聯創建的InputStream是否由GC自動關閉?

我知道這足以關閉外部流,它將關閉在內部創建的內部流。

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

考慮下面的例子

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

如若FileInputStream被分配給一個變量,然後關閉明確(或者try-與資源建設),或將Java的GC之後props.load()方法自動關閉調用,因爲沒有對資源的引用?

+1

'GB'是什麼意思? – biziclop

+1

您不應該依靠垃圾回收器來執行資源釋放。對你的問題的正確答案是「可能或不可能」。 –

+0

詳細闡述@ M.Prokhorov的評論:當垃圾收集器能夠完成它的工作時,並不能保證,原則上它可以無限期地延遲其工作,這意味着資源將被無限期地分配,這不是你想要的。明確關閉資源,而不是依賴GC。 – Jesper

回答

6

的Javadoc指出

指定的流保持此方法返回後開放。

所以是的,如果你想寫乾淨的代碼,你應該自己關閉它。 GC將最終關閉它,如果它在流上調用finalize()方法(如下所示),但您shouldn't rely on that

請務必關閉您的資源,這是確保您的唯一途徑。

/** 
* 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

必須強調的是,使用像

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

代碼強烈反對,因爲收盤不會發生,如果流建設和close()通話之間的操作拋出異常。

您應該使用「與資源嘗試」構建代替:

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

這確保了close()將即使在try身體發生異常調用。然而,該代碼依賴於已知的事實,即BufferedInputStream的方法將調用FileInputStream的方法,但是這種情況在BufferedInputStream的構建完成之前不會發生。如果BufferedInputStream的構造函數拋出異常,則不會調用close()方法,因爲沒有對象可以調用close()

一個真正安全的解決方案是

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

,其封閉FileInputStream即使BufferedInputStream的構造函數拋出異常。這可能看起來像是一個罕見的角落案例,因爲在構造函數中唯一可能出錯的是緩衝區分配,它可能會拋出一個OutOfMemoryError,並且在這種情況下你總是陷入困境。

但考慮像

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

爲例由於ObjectInputStream構造已經讀取頭,IOException S可以被拋出,也,頭部可能是無效的,這也將導致異常。因此,即使在這些情況下,還有很多可能出錯並確保底層FileInputStream被正確關閉更重要。

相關問題