2016-07-01 11 views
3

Muleで動作するJavaアプリケーションがあります。 XMXの値は6144Mに設定されていますが、全体的なメモリ使用量の上昇と上昇を定期的に確認しています。私たちが積極的にそれを再開する前に、先日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のは同じ値に設定されているため、Javaヒープのため6291456Kの単一の割り当てがあることを私に言っているように見えます。他の割り当ては、Javaのヒープメモリではありません。彼らは何ですか?彼らはかなり大きなチャンクに割り当てられています。

+0

ない正しい答えを、私はそれがネットワーク・バッファで発生持っていました。あなたがマルチキャストに加入していてそれを読んでいない(またはそれをゆっくり読んでいる)場合、インバウンドバッファは巨大なサイズに成長する可能性があります(私は10のGBを観察しました)。たぶんそれは他のネットワークにも当てはまります。私は、プロセスメモリダンプを効果的に分析する方法を見つけたわけではありません。残念なことに粗いビューではなく、実際の回答に非常に興味があります。 – Ordous

+2

ダイレクトByteBufferメモリをチェックします(MXBean 'java.nio:type = BufferPool'で利用可能)。 [ネイティブ・メモリー・トラッキング](https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html)機能も試してください。 – apangin

+0

私はまだJava 7を実行しているので、ネイティブメモリトラッキングは私にとってはオプションではないようです。しかし、本当に便利ですね。 – Galuvian

答えて

1

ピーターの答えについてもう少し詳しく説明します。

VisualVM内からバイナリヒープダンプを取ることができます(左側のリストのプロセスを右クリックしてからヒープダンプをクリックするとすぐにそのすぐ下に表示されます)。あなたのJVMにVisualVMのを添付することができない場合は、これでダンプを生成できます。

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

次に、ファイルをコピーして、Visual VM(ファイル、ロード、選択型ヒープダンプで開き、ファイルを見つけます。)

Peterがメモしているように、リークの原因はDirectByteBuffersを収集していない可能性があります(例:別のクラスのインスタンスがバッファを適切に参照解除していないためGC'Dできません)。

これらの参照がどこに由来するのかを特定するには、Visual VMを使用して、「クラス」タブでヒープを調べ、DirectByteByfferのすべてのインスタンスを見つけることができます。 DBBクラスを見つけて右クリックし、インスタンスビューに移動します。

これにより、インスタンスのリストが表示されます。あなたがいずれかをクリックし、それぞれの参照を維持するユーザーがわかる:

Visual VM - Instances view

注下のペインに、我々は、型クリーナーと2「mybuffer」の「参照先」を持っています。これらは、掘削したDirectByteBufferのインスタンスを参照している他のクラスのプロパティです(Cleanerを無視して他のものに重点を置くと問題はありません)。

この時点から、アプリケーションに基づいて処理を進める必要があります。

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オブジェクトを示しました。それらの大部分はcom.mapr.fs.jni.Pageに関連付けられています。私は彼らのサポートに連絡しました。 – Galuvian

1

あなたができることは、ヒープダンプを取って、ByteBuffersのようなヒープのデータを格納しているオブジェクトを探します。これらのオブジェクトは小さく見えますが、ヒープ・メモリー領域が大きくなるとプロキシーになります。彼らの多くが保持される理由を判断できるかどうかを確認してください。

関連する問題