web-dev-qa-db-ja.com

私のJavaヒープダンプサイズが使用済みメモリよりもはるかに小さいのはなぜですか?

問題

Webアプリケーションで大きなメモリリークの原因を見つけようとしています。メモリリークを見つける経験はかなり限られていますが、jmapを使用してJavaヒープダンプを作成し、EclipseMATで分析する方法を見つけました。

ただし、56/60GBメモリを使用するアプリケーションでは、ヒープダンプのサイズはわずか16GBであり、EclipseMATではさらに小さくなります。

環境

サーバーは、Ubuntu14.04上のWildfly8.2.0をJavaアプリケーションに使用し、そのプロセスは使用可能なメモリの95%を使用します。ダンプを作成するとき、バッファー/キャッシュの使用済みスペースは56GBでした。

次のコマンドを使用してダンプを作成しました。Sudo -u {application user} jmap -dump:file=/mnt/heapdump/dump_prd.bin {pid}

ヒープダンプファイルのサイズは16.4GBであり、Eclipse MATで分析すると、約1GBのライブオブジェクトと最大14,8GBの到達不能/浅いヒープがあることがわかります。

編集:これが私たちが起こっていると思う問題についてのいくつかのより多くの情報です。メモリ使用量を監視し、最大300 MBの空きメモリが残るまで、メモリ使用量が増加していることを確認します。その後、プロセスがクラッシュするまで、残念ながらアプリケーションログにエラーが発生することなく、その量のメモリを維持します。

これは、メモリがほぼ枯渇した場合にのみ発生するため、ハードOOMエラーであると想定します。設定を使用します-Xms25000m -Xmx40000mJVM用。

質問

基本的に、メモリの大部分がこのダンプにキャプチャされないのはなぜか疑問に思っています。上位の保持サイズクラスはそれほど疑わしいようには見えないので、ヒープダンプに関連する何かが間違っているのではないかと考えています。

11
Thermometer

ヒープをダンプするとき、JVMは最初にガベージコレクションサイクルを実行して、到達不能なオブジェクトを解放します。

最初にガベージコレクションを行わずにJava 5でヒープダンプを取得するにはどうすればよいですか?

私の経験では、アプリケーションが利用可能なヒープスペースよりも多くのヒープスペースを要求している真のOutOfMemoryErrorでは、このGCはばか者の用事であり、最終的なヒープダンプは最大サイズになります。ヒープサイズ。

ヒープダンプがはるかに小さい場合、それはシステムが本当にメモリ不足ではなかったことを意味しますが、おそらくメモリ不足がありました。たとえば、Java.lang.OutOfMemoryError: GC overhead limit exceededエラーがあります。これは、JVMが新しい割り当て要求を処理するのに十分なメモリを解放できた可能性があるが、ガベージの収集に多くの時間を費やさなければならなかったことを意味します。

メモリの問題がない可能性もあります。どうして自分がそうだと思いますか?ヒープの使用法やOutOfMemoryErrorについては何も言及していません。オペレーティングシステムでのJVMのメモリフットプリントについてのみ言及しました。

16
Brandon

私の経験では、ヒープダンプが実際に使用されているメモリよりもはるかに小さいのは、JNIのリークが原因である可能性があります。

ネイティブコードを直接使用しないにもかかわらず、それを使用して高速化する特定のライブラリがあります。

私たちの場合、それは Deflater および Inflater が適切に終了していませんでした。

3
jcoll