2

我正在使用Java的保存和加載文件的應用程序,所以我使用的是流。我從文件中獲取流,然後使用此流在另一個文件夾中創建一個新文件。問題是,在使用流並關閉它之後,應該釋放的內存仍然存在。InputStream發生內存泄漏?

例如,我加載100MB的文件(任務管理器顯示,在100MB的java.exe增加),那麼我將文件保存在另一個文件夾,並用stream.close關閉流()。但是,java.exe不會減少100MB。當我多次保存和加載文件,並且java.exe超過600MB時,它會減少到300 MB。每次它將超過600mb,它會減少到300mb。爲什麼是這樣?爲什麼當我調用stream.close()時,內存不能達到0mb?爲什麼它在600mb的時候釋放內存,並沒有釋放所有的內存?

這是我從路徑字符串加載一個流,然後關閉流:

String path = ... //File path 
InputStream stream = new BufferedInputStream(new FileInputStream(path)); 
stream.close(); 

感謝您的答覆。

+3

如果您決定使用該內存,您可能會簡單地將其釋放以供您使用,這意味着「過度」使用是無關緊要的。垃圾收集並不總是立即發生;請參閱http://javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html –

+0

向操作系統釋放內存非常昂貴。 –

+0

我的印象是,Java只會很少釋放內存給操作系統 - 絕對不是在小規模的收藏期間。這是基於這樣的假設:大多數需要一定量X內存的軟件遲早會需要它。 – millimoose

回答

2

你看到什麼是Java內存系統的正常運作,分配的內存就不一定返還給OS。

您應該使用內存分析器(例如內置的JConsole工具(或免費的Eclipse MAT進行更深入的分析))來檢查OS級別上的java.exe的內存。

-1

在你的代碼的FileInputStream是匿名的實例。

由於大文件,它可以存儲在虛擬內存/虛擬內存。它不會關閉,直到java開始垃圾回收。

創建的FileInputStream新的命名實例,靠近

它應該工作

+1

-1:在「匿名實例」和「命名實例」中沒有這樣的事情 - 將'FileInputStream'分配給本地變量會導致行爲沒有區別。 'BufferedInputStream'在稍微清理後關閉底層緩衝流。 – millimoose

+0

我試着用它作爲局部變量而不是,結果是一樣的。不管怎麼說,還是要謝謝你。 –

+2

答案沒有意義。 – EJP

4

的BufferedInputStream默認因此它不能漏氣超過8 KB(加上一個小的開銷)使用8 KB的固定大小

我打開一個100MB的文件(任務管理器顯示,在100MB的java.exe增加),

這意味着您正在使用100 MB的對象來處理文件。

不過的java.exe不會降低100MB

沒有理由它應該。它很可能會在GC之後,但你不想這樣做,除非你需要,我懷疑你不這樣做。

每次它將超過600MB,它會減少到300MB。爲什麼是這樣?

你有觸發垃圾收集。很可能是一個小集合。

當我調用stream.close()時,爲什麼內存不能到0mb?

當它開始時,它不是0 MB,當你GC時,你會回憶回憶,但你不想這樣做是不必要的。

爲什麼它在600mb空閒時釋放內存,並且它不釋放所有內存?

它有多個內存區域,它試圖做最簡單的工作,通常是清洗伊甸園空間。

+0

「最有可能的小收藏品」 - 不會有小的收藏品就能騰出伊甸園空間。我的印象是,在一次GC中,倖存者只能從伊甸園移到老一代,讓所有的伊甸園都能再次獲得。這意味着一個小集合實際上會增加內存使用量,而不會減少它。 (也就是說,這是基於對舊版HotSpot世代清除白皮書/指南的模糊回憶,現在的情況可能會有所不同。) – millimoose

+0

小集合釋放了年輕一代,其中包括倖存者空間。一旦eden空間被清除,你將永遠不會得到比你剛開始時更多的數據。 –

+0

是的,但是這個集合是否會釋放內存到操作系統? – millimoose