2014-10-27 131 views
3

我有一個應用程序使用大量的內存區分兩個潛在巨大(100k +)目錄的內容。對我來說這樣的操作會使用大量的內存是有意義的,但是一旦我的差異操作完成,堆仍然保持相同的大小。減少Java堆大小

我基本上擁有實例化類的代碼,用於存儲源和目標上每個文件的文件名,文件大小,路徑和修改日期。我保存其他陣列中的添加,刪除和更新。我然後clear()我的源和目標數組(現在可能每個100k +),留下相對較小的添加,刪除和更新數組。

之後我clear()我的目標和源數組雖然,內存使用情況(通過VirtualVM和Windows任務管理器可見)不會下降。我對VirtualVM(或任何關於此事的分析器)沒有足夠的經驗來弄清楚什麼是佔用所有這些內存。 VirtualVM的堆轉儲列出了保留大小爲幾兆字節的前幾個對象。

任何幫助指向正確方向的東西?

+1

你確定垃圾收集器已經運行,當你看內存使用情況?內存使用率只會在GC(可能是主要的)運行後下降。 – cello 2014-10-27 08:03:47

+0

根據virtualvm,堆保持大致相同,而使用的堆將下降(大約我期望它,這是少於總堆的一半)。堆大小與Windows任務管理器告訴我java正在使用的內容大致相符。在分析應用程序時,我會看到通常的GC樓梯集合模式,我只是不知道爲什麼總堆仍然如此之大。 – tau 2014-10-27 08:14:21

回答

2

如果使用的堆在垃圾回收之後下降,比它有可能按預期工作。當Java需要更多內存時,Java會增加它的堆,但不會釋放它 - 它更喜歡保持它以防應用程序再次使用更多內存。有關此主題的信息,請參閱Is there a way to lower Java heap when not in use?,瞭解爲什麼在使用的堆量減少後堆沒有減少。

+0

我只是瞥了一眼那個線程,它已經非常翔實。謝謝! – tau 2014-10-27 08:27:27

1

根據你的代碼,你可能會產生內存泄漏,垃圾收集器不能釋放它們。

我會建議您測試您的代碼以便發現潛在的內存泄漏。一旦排除或修復,我會開始查看代碼本身以尋求可能的改進。

請注意,例如,如果您使用try/catch/finally塊。 finally塊可能根本不會被調用(或者至少不會立即)。如果你在finally塊中釋放一些資源,這可能是答案。

然而讀了關於這個問題的,比如這裏:http://www.toptal.com/java/hunting-memory-leaks-in-java

2

虛擬機根據命令行參數-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio增大或縮小堆。當空閒百分比達到-XX:MaxHeapFreeRatio時,它將縮小堆積,其默認值爲70.

Oracle's bug #6498735中有對此的簡短討論。