2013-08-29 79 views
3

Java對象沒有生命週期,這由garbage collector管理。如果我使用某些IO類而不關閉它,或者某些DBConnection,這會不會考慮資源泄漏?也就是說,IO對象是否會被垃圾收集器AFAIK收集並銷燬,垃圾收集器僅用於內存。例如:將流類或連接視爲Java中的資源泄漏

BufferedReader br = new BufferedReader(new FileReader(new File("path"))); 

回答

4

是的你是對的。垃圾收集釋放Java堆(內存),但close()釋放用於打開文件的操作系統資源(在大多數系統上打開文件的數量是有限的),並確保數據真正寫入。

但是很多類如FileInputStreamRandomAccessFile都是用一個finalize()方法編寫的,該方法確保瞭如果垃圾回收的close()實例將被首先調用。所以在很多情況下,垃圾回收會間接釋放文件,程序員通常可能懶得關閉資源,因爲垃圾回收通常會爲您清理它們。不幸。

問題是,您無法控制何時發生這種情況,而且可能根本不會發生。所以如果打開的文件太多,操作系統可能會在垃圾收集器關閉它們之前給你一個錯誤信息。或者,如果您想在移動文件或刪除文件後立即閱讀文件,移動或刪除操作可能會失敗,因爲那時您仍然可以打開文件以供閱讀。

像這樣的錯誤往往難以可靠地重現,因爲它們取決於垃圾回收器的時間。所以你得到的東西通常工作得很好,但有時會神祕地失敗。非常煩人的調試。出於這個原因,我們強烈建議您儘快關閉()您可能正在使用的任何流/讀取器/連接或其他可關閉資源。最好在finally塊中,確保即使在處理中發生其他錯誤時也會發生這種情況。

而且隨着Java 7的推出,還增加了一個接口AutoClosable,詳細瞭解它吧here

價:http://www.coderanch.com/t/278165//java/InputStream-close-garbage-collection

+0

就這樣!我在某處讀到了「敲定」,這解釋了爲什麼我們需要它。但我也讀過,不要依賴'敲定'這個聲明怎麼樣? – zoujyjs

+2

@zoujyjs使用「finalize」只會創建額外的GC開銷。關閉應該通過try..catch..finally完成。但如果無法保證,您可能需要使用finalize。 –

+0

在上面添加到Sajal的輸入中,基本上你不應該依賴其他任何東西,並且當你完成它時明確關閉你的流/連接。 – Amar

1

「Java對象沒有生命週期,這是由垃圾收集器管理的。」 - 不完全正確。它首先由程序編寫的方式「管理」。如果一個對象超出範圍,GC很可能會處理它。

如果您不關閉br,它將一直存在,直到程序退出,除非通過GC收集,如果準備收集。它不會泄漏,只是一個漫長的生活變量。

+0

它將一直存在,直到它符合GC的條件並且是GCed;這可能是也可能不是應用程序的生命週期。 –

+0

@DaveNewton是的,這是正確的,但最壞的情況是 - 它不會,你也不能強迫。您可能希望通過System.gc()調用來引起其注意,但不保證收集。我應該編輯措辭。 –

1
And if I use some IO classes without closing it, or some DBConnection, will 
this considered a resource leak? 

使用相同IO類說是錯誤的術語。如果您創建資源/連接,然後在不實際關閉原始資源的情況下使用其資源的引用,那麼如果沒有對原始資源的活動引用,那麼它將符合GC的條件。

但是,直到原始資源被GCed時,所有的操作系​​統資源(文件句柄等)都不會被釋放。當對象受到GC(在該對象/資源上調用finalize()方法)時,首先調用close(),因爲釋放了與操作系統有關的資源,然後釋放堆內存。

例如,考慮的FileInputStream finalize()方法是如下

protected void finalize() throws IOException { 
    if ((fd != null) && (fd != FileDescriptor.in)) { 

     /* 
     * Finalizer should not release the FileDescriptor if another 
     * stream is still using it. If the user directly invokes 
     * close() then the FileDescriptor is also released. 
     */ 
     runningFinalize.set(Boolean.TRUE); 
     try { 
      close(); 
     } finally { 
      runningFinalize.set(Boolean.FALSE); 
     } 
    } 
} 

你看近()首先調用。

因此,儘管GC爲您處理內存管理,但在不需要它時關閉finally語句中的資源是一種很好的編程習慣。