本文介紹了Java Heap dump:如何通過1.io.netty.Buffer.ByteBufUtil 2.byte[]數組查找占用內存的對象/類的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我發現我的一個Spring Boot項目的內存(RAM消耗)每天都在增加。當我將JAR文件上傳到AWS服務器時,它占用了582MB的RAM(最大分配的RAM是1500MB),但是每天的RAM都在增加50MB到100MB,5天后的今天,它占用了835MB。目前項目用戶規模為100-150人,睡覺API使用正常。
由于RAM的增加,應用程序多次關閉,并出現以下錯誤(從日志中發現錯誤):
Exception in thread "http-nio-3384-ClientPoller" java.lang.OutOfMemoryError: Java heap space
因此,為了解決這個問題,我發現通過使用Java Heap轉儲,我可以找到占用內存的對象/類。因此,通過在命令行中使用Jmap
,我已經創建了一個堆轉儲,并將其上傳到Heap Hero和Eclipse Memory Analyzer Tool。在這兩個文件中,我發現了以下內容:
1.總浪費內存為:64.69MB(73%)(查看下面的截圖)
2。其中34.06MB被Byte [] array
和LinkedHashmap[]
占用(請查看下面的截圖),這是我在整個項目中從未使用過的。我在我的項目中搜索了它,但沒有找到。
3。以下兩個大對象分別占用32MB和20MB。
1. Java Static io.netty.buffer.ByteBufUtil.DEFAULT_ALLOCATOR
2. Java Static com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.connectionFinalizerPhantomRefs`
所以我試圖找到這個netty.buffer。在我的項目中,但我找不到任何與netty或Buffer匹配的內容。
現在我的問題是如何減少此內存泄漏或如何找到確切的內存消耗對象/類/變量以便減小堆大小。
我知道很少有專家會要求提供源代碼或類似的東西,但我相信從堆轉儲中可以找到內存中可用的內存泄漏或活動對象。我正在尋找該選項或任何可以減少此堆轉儲的選項!
我在過去的3周里一直在處理這個問題。任何幫助都將不勝感激。
謝謝!
推薦答案
首先啟用JVM native memory tracker,通過添加標志-XX:NativeMemoryTracking=summary
了解內存的哪個部分在增加。根據文檔,存在一些性能開銷(5-10%),但如果這不是問題,我建議即使在生產中也啟用此標志來運行JVM。
然后您可以使用jcmd <PID> VM.native_memory
檢查這些值(此答案中有一個很好的記錄:Java native memory usage)
如果確實分配了很大的本機內存塊,則很可能是由Netty分配的。
您如何在AWS中運行您的應用程序?如果它在Docker映像中運行,您可能會遇到這個問題:What would cause a java process to greatly exceed the Xmx or Xss limit?
在這種情況下,如果您的應用程序使用本機內存(Netty就是這樣)并在具有大量內核的服務器上運行,則可能需要設置環境變量MALLOC_ARENA_MAX
。完全有可能的是,JVM為Netty分配了這個內存,但是沒有看到任何釋放它的理由,因此它看起來只會繼續增長。
如果您想控制Netty可以分配多少本機內存,您可以為此使用JVM標志-XX:MaxDirectMemorySize
(我相信默認值與Xmx
相同),并在您的應用程序不需要那么多內存的情況下降低它。
JVM內存調優是一個復雜的過程,當涉及到本機內存時,它會變得更加復雜-正如鏈接的答案所示,它不像簡單地設置Xms
和Xmx
標志并期望不再使用內存那么簡單。
這篇關于Java Heap dump:如何通過1.io.netty.Buffer.ByteBufUtil 2.byte[]數組查找占用內存的對象/類的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,