簡體   English   中英

JVM內存使用失控

[英]JVM memory usage out of control

我有一個Tomcat webapp,它代表客戶端執行一些漂亮的內存和CPU密集型任務。 這是正常的,是所需的功能。 但是,當我運行Tomcat時,內存使用量會隨着時間的推移而猛增至4.0GB以上,此時我通常會殺死該進程,因為它會破壞我在開發計算機上運行的所有其他內容:

在此輸入圖像描述

我以為我無意中用我的代碼引入了內存泄漏,但在用VisualVM檢查后,我看到了一個不同的故事:

在此輸入圖像描述

VisualVM顯示堆占用大約一GB的RAM,這就是我用CATALINA_OPTS="-Xms256m -Xmx1024"

根據VisualVM的說法,為什么我的系統認為這個過程占用了大量的內存,它幾乎沒有占用任何內容?


經過一番進一步的嗅探,我注意到如果在應用程序中同時運行多個作業,則內存不會被釋放。 但是,如果我在將另一個作業提交給由ExecutorService提供服務的BlockingQueue之前等待每個作業完成,那么內存將被有效地回收。 我該怎么調試呢? 為什么垃圾收集/內存重用會有所不同?

您無法控制要控制的內容-Xmx僅控制Java堆,它不控制JVM對本機內存的消耗,而JVM根據實現完全不同地使用。 VisualVM只顯示Heap正在消耗的內容,它不會顯示整個JVM作為本機內存消耗的操作系統進程。 您將不得不使用操作系統級工具來查看它,並且它們將報告完全不同的數字,通常比VisualVM報告的任何數字都大得多,因為JVM以完全不同的方式使用本機內存

從以下文章感謝內存(了解JVM如何在Windows和Linux上使用本機內存)

維護堆和垃圾收集器使用您無法控制的本機內存。

需要更多的本機內存來維護維護Java堆的內存管理系統的狀態。 必須分配數據結構以跟蹤免費存儲並記錄收集垃圾時的進度。 這些數據結構的確切大小和性質隨實現而變化,但許多與堆的大小成比例。

並且JIT編譯器使用本機內存,就像javac一樣

字節碼編譯使用本機內存(與gcc等靜態編譯器需要運行內存的方式相同),但JIT的輸入(字節碼)和輸出(可執行代碼)也必須存儲在本機內存中。 包含許多JIT編譯方法的Java應用程序比較小的應用程序使用更多的本機內存。

然后你有使用本機內存的類加載器

Java應用程序由定義對象結構和方法邏輯的類組成。 它們還使用Java運行時類庫(例如java.lang.String)中的類,並且可以使用第三方庫。 只要它們被使用,這些類就需要存儲在內存中。 如何存儲類因實現而異。

我甚至不會開始引用關於Threads的部分,我想你會認為-Xmx不能控制你認為它控制的是什么,它控制着JVM堆,而不是JVM堆中的所有內容,並且堆占用了更多的本機記憶,你指定的管理和簿記。

簡單而簡單的JVM使用的內存比-Xms-Xmx以及其他命令行參數中提供的內存更多。

這里有一篇關於JVM如何分配和管理內存非常詳細的文章 ,它並不像你在問題中的假設所期望的那樣簡單,值得全面閱讀。

許多實現中的ThreadStack大小具有最小限制,這些限制因操作系統和JVM版本而異; 如果將限制設置為低於JVM或OS的本機操作系統限制,則會忽略threadstack設置(有時必須設置ulix on * nix)。 其他命令行選項以相同的方式工作,當提供的值太小時,默認默認為更高的值。 不要假設傳入的所有值都代表實際使用的值。

類加載器和Tomcat有不止一個,占用了大量內存,而這些內存很難被記錄下來。 JIT占用了大量的內存,隨着時間的推移交易空間,這在大多數情況下是一個很好的交易。

您還應該檢查CPU使用情況和垃圾收集器。
垃圾收集可能會暫停 ,並且CPU gc會進一步降低機器的運行速度。

暫無
暫無

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

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