簡體   English   中英

為什么這個java進程不釋放內存?

[英]Why does this java process not release memory?

我編寫了一個java應用程序,我在Fedora 24下運行了java進程。然后我檢查了jconsole,發現它使用了大約5到10兆字節的內存。 垃圾收集的效果在圖中也可見。

這是截圖: jconsole截圖

然后我檢查了我的系統監視器,發現相同的進程ID有超過100兆字節的內存使用量。

這是截圖:

系統監視器截圖

請告訴我為什么這個過程沒有釋放未使用的內存?

有沒有辦法釋放它?

使用的堆和已分配的堆之間存在差異。 圖中的藍線是用過的堆 - 實際持有對象的堆的數量。 未顯示的是分配的堆的大小 - 這個更大,通常要大得多,這樣JVM可以分配更多的對象而不會耗盡空間並且必須返回操作系統以獲得更多內存(這是昂貴的) )。 在您的情況下,系統顯示的100mb中的一些是JVM本身,但其中大部分可能已分配但未使用的堆。

當您運行Java程序而未指定您希望它使用的堆大小時,JVM將嘗試根據您的計算機,操作系統,JVM版本等找出合理的設置。當我在16GB的機器上運行簡單的Hello World時在RAM和Java 8中,它最初為堆分配了256mb。 顯然遠遠超過它的需要! 如果我想強制它使用less,我可以使用-Xms命令行設置初始堆分配,使用-Xmx設置允許的最大值。 我的猜測是,如果你設置像-Xms20m類的-Xms20m你會發現你的進程使用的內存更少。 在IntelliJ中,將該設置添加到運行配置中的VM Options字段。

系統監視器中報告的內存是進程使用的所有內存,而不僅僅是Java堆。 這個記憶包括:

  • VM本身的可執行文件及其加載的庫
  • 對於VM的工作空間在這樣的事情作為熱點編譯器,GC,IO緩沖區,屏幕和圖形緩沖的過程 ,閱讀VM文件等
  • Java堆和其他可報告的內存結構

在您的情況下,正在使用10MB的進程來存儲Java堆棧和Java對象。 另一個90MB是Java程序本身和VM內部的內存。

這是簡短的答案,但還有另一個重要的考慮因素 - Java可以(並且確實)將多余的堆釋放回操作系統。 這由-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio標志控制。 默認情況下,MaxHeapFreeRatio是70% - 這幾乎就是你的Heap圖中顯示的內容(鋸齒圖案從6MB到10MB以下)。 如果您的應用程序具有明顯更大的下降,您將在系統監視器中看到Java進程的(小)鋸齒模式。

為了提高性能,通常應該允許JVM保留從GC中釋放的大量堆。 為什么? 因為我們知道JVM將立即需要再次開始分配內存,並且Java的進程(和操作系統)更有效地保持這一點。

所以,總結一下:

  • 系統監視器顯示整個JVM進程使用的內存
  • Java堆只是進程中使用內存的項目之一
  • (通常)JVM保持(至少某些)它在GC之后釋放的堆的性能(通常)更高,因為我們幾乎肯定會在接下來的幾秒鍾內使用它
  • 在這種情況下,Java堆在正常范圍內振盪,在這種情況下,默認的內存配置允許Java在GC之后保存所有多余的堆

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM