2016-07-01 17 views
3

我們有一個運行在Mule上的java應用程序。我們爲6144M配置了XMX值,但通常會看到整個內存使用率攀升和攀升。在我們主動重新啓動它之前,前一天接近20 GB。如何調試JVM上本機內存中的泄漏?

Thu Jun 30 03:05:57 CDT 2016 
top - 03:05:58 up 149 days, 6:19, 0 users, load average: 0.04, 0.04, 0.00 
Tasks: 164 total, 1 running, 163 sleeping, 0 stopped, 0 zombie 
Cpu(s): 4.2%us, 1.7%sy, 0.0%ni, 93.9%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st 
Mem: 24600552k total, 21654876k used, 2945676k free, 440828k buffers 
Swap: 2097144k total, 84256k used, 2012888k free, 1047316k cached 

    PID USER  PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 
3840 myuser 20 0 23.9g 18g 53m S 0.0 79.9 375:30.02 java 

的JPS命令顯示:

10671 Jps 
3840 MuleContainerBootstrap 

的jstat命令顯示:

S0C S1C S0U S1U  EC  EU  OC   OU  PC  PU YGC  YGCT FGC FGCT  GCT 
37376.0 36864.0 16160.0 0.0 2022912.0 1941418.4 4194304.0 445432.2 78336.0 66776.7 232 7.044 17  17.403 24.447 

啓動自變量(敏感位改變):

3840 MuleContainerBootstrap -Dmule.home=/mule -Dmule.base=/mule -Djava.net.preferIPv4Stack=TRUE -XX:MaxPermSize=256m -Djava.endorsed.dirs=/mule/lib/endorsed -XX:+HeapDumpOnOutOfMemoryError -Dmyapp.lib.path=/datalake/app/ext_lib/ -DTARGET_ENV=prod -Djava.library.path=/opt/mapr/lib -DksPass=mypass -DsecretKey=aeskey -DencryptMode=AES -Dkeystore=/mule/myStore -DkeystoreInstance=JCEKS -Djava.security.auth.login.config=/opt/mapr/conf/mapr.login.conf -Dmule.mmc.bind.port=1521 -Xms6144m -Xmx6144m -Djava.library.path=%LD_LIBRARY_PATH%:/mule/lib/boot -Dwrapper.key=a_guid -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.disable_console_input=TRUE -Dwrapper.pid=10744 -Dwrapper.version=3.5.19-st -Dwrapper.native_library=wrapper -Dwrapper.arch=x86 -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 -Dwrapper.lang.domain=wrapper -Dwrapper.lang.folder=../lang 

添加「容量」項目從jps顯示只有我的6144m被用於java堆。哪裏是剩下的內存正在使用?堆棧內存?本地堆?我甚至不知道如何繼續。

如果讓它繼續增長,它會佔用系統上的所有內存,並且最終會看到系統凍結導致交換空間錯誤。

我有另一個開始增長的過程。目前約有11g的常駐記憶。

pmap 10746 > pmap_10746.txt 
cat pmap_10746.txt | grep anon | cut -c18-25 | sort -h | uniq -c | sort -rn | less 

Top 10 entries by count: 
    119  12K 
    112 1016K 
    56  4K 
    38 131072K 
    20 65532K 
    15 131068K 
    14 65536K 
    10 132K 
     8 65404K 
     7 128K 


Top 10 entries by allocation size: 
    1 6291456K 
     1 205816K 
     1 155648K 
    38 131072K 
    15 131068K 
     1 108772K 
     1 71680K 
    14 65536K 
    20 65532K 
     1 65512K 

And top 10 by total size: 
Count Size Aggregate 
1 6291456K 6291456K 
38 131072K 4980736K 
15 131068K 1966020K 
20 65532K 1310640K 
14 65536K 917504K 
8 65404K 523232K 
1 205816K 205816K 
1 155648K 155648K 
112 1016K 113792K 

這似乎是在告訴我,因爲XMX和XMX被設置爲相同的值,有6291456K爲Java堆單分配。其他分配不是Java堆內存。他們是什麼?他們正在分配相當大的塊。

+0

不是一個正確的答案,但是我在網絡緩衝區中發生過這種情況。顯然,如果你訂閱了多播並且不讀取它(或者緩慢讀取它),入站緩衝區可以增長到很大的大小(我已經觀察到了10的GB)。也許這對其他網絡來說是真的。我還沒有找到有效分析進程內存轉儲的方法,不幸的是,即使是粗略的視圖(並且對實際的答案會很感興趣)。 – Ordous

+2

檢查直接ByteBuffer內存(可通過MXBean'java.nio:type = BufferPool'獲得)。試試[Native Memory Tracking](https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html)功能。 – apangin

+0

我仍在運行Java 7,所以它看起來像本機內存跟蹤不是我的選擇。雖然看起來非常有用。 – Galuvian

回答

1

在彼得的答案上增加一些細節。

您可以從VisualVM中獲取二進制堆轉儲(右鍵單擊左側列表中的進程,然後在堆轉儲上 - 它會立即顯示在下面)。如果您無法連接的VisualVM你的JVM,還可以生成與此轉儲:

jmap -dump:format=b,file=heap.hprof $PID 

然後複製該文件,並使用Visual VM(文件,加載,選擇類型堆轉儲打開它,找到該文件)

正如彼得指出的,泄漏的可能原因可能是非收集的DirectByteBuffers(例如:另一個類的某個實例沒有正確地取消引用緩衝區,所以它們從不GC'd)。

要確定這些引用來自哪裏,可以使用Visual VM檢查堆並在「類」選項卡中查找DirectByteByffer的所有實例。找到DBB類,點擊右鍵,進入實例視圖。

這會給你一個實例列表。您可以點擊一個,看看誰是保持基準每一個:

Visual VM - Instances view

注意底部窗格中,我們有清潔型和2「mybuffer」的「參照物」。這些屬性是其他類中的屬性,它們引用我們鑽入的DirectByteBuffer實例(如果忽略清除程序並專注於其他程序,應該可以)。

從這一點開始,您需要根據您的應用程序進行操作。

獲得DBB實例列表的另一種等效方法是從OQL選項卡獲取。此查詢:

select x from java.nio.DirectByteBuffer x 

給我們提供了和以前一樣的清單。使用OQL的好處是您可以執行更多more complex queries。例如,這會得到所有保留對DirectByteBuffer引用的實例:

select referrers(x) from java.nio.DirectByteBuffer x 
+0

感謝您的詳細解釋。 VisualVM無法加載我的堆轉儲,但MAT是。它顯示了130萬個DirectByteBuffer對象,即使在強制gc之後。他們中的大多數與com.mapr.fs.jni.Page關聯。我已經聯繫他們的支持。 – Galuvian

1

你可以做的是採取一個堆轉儲,並尋找存儲數據的堆對象,如ByteBuffers。這些對象看起來很小,但代表較大的堆內存區域。看看你是否可以確定爲什麼可以保留大量這些。