5

簡単な質問

jmapヒープダンプには、古い世代のみが含まれますか、それとも若い世代も含まれますか?


長い説明

私は2つのヒープダンプを持っています(jmap -heap:format=b 9999):

  • 負荷のない(HTTPリクエストのない)サーバーの1つ
  • 1つはCPUを50%動作させ、高負荷(ベンチマーク)

さて、最初のダンプは2番目よりも大きいヒープサイズを示しています(これは奇妙だと思いました)。

これは、ガベージコレクターが頻繁に実行されているために(高負荷の)若い世代が頻繁に変更されているためでしょうか(はい、JVMはほぼ満杯です)。古い世代は99%でいっぱいですが、若い世代のスペース使用量は大きく異なることに気づきました。

つまり、GCが仕事をした直後に2番目のダンプを作成したということです。これが、そのサイズが小さい理由です。私は正しいですか?

追加情報

Java引数:

-XX:+UseParallelGC -XX:+AggressiveHeap
-Xms2048m -Xmx4096m -XX:NewSize=64m
-XX:PermSize=64m -XX:MaxPermSize=512m
4

1 に答える 1

10

素早い回答

両方-ヒープは、若い世代と古い世代で構成されています。したがって、ヒープダンプを取得すると、コンテンツには両方が含まれます。ヒープダンプの統計は分離する必要があります。コマンドのバイナリ部分を削除して、プレーンテキストで確認してください。構成の概要と、各世代の内訳が表示されます。反対に、-histoは、ヒープ上のすべてのオブジェクトを区別せずに表示するだけです。

長い答え

2番目のプロセスのガベージコレクションが終了したばかりである可能性があります。またはその逆に、最初のプロセスはしばらくの間完全なコレクションを持っておらず、より高いメモリに座っていた可能性があります。このアプリケーション/サーバーは、キャプチャを取得したときに再起動したばかりですか?のようなツールを使用してアイドル状態のプロセスをjvisualvm見ると、プロセスが何の作業も行っていない場合でも、メモリ割り当てグラフが上下に移動することがわかります。これは、JVMが独自のことをしているだけです。

通常、フルGCは、旧世代で99%のマークに達する前に開始する必要があります。JVMは、フルGCを実行するタイミングを決定します。これはオブジェクトが最も速く作成/削除される場所であるため、YoungGenは大きく変動します。完全なGCが実行される前に、若い世代を一掃するために多くの部分的なGCが実行されます。2つの違いは、JVMアクティビティの一時停止を意味します。部分的なGCを確認しても、アプリケーションに悪影響はありません。ただし、完全なGCの一時停止時間は、実行中にアプリケーションを停止します。したがって、可能な限りそれらを最小限に抑えたいと思うでしょう。

メモリリークを探している場合、またはアプリケーションのgcがどのように機能しているかを確認するためのプロファイリングを行っている場合は、起動フラグを使用してガベージコレクションの統計を出力することをお勧めします。

-XX:+PrintGCDetails -verbose:gc -Xloggc:/log/path/gc.log

プログラムをしばらく実行してから、キャプチャしたログをツールにロードして、結果を視覚化するのに役立ててください。私は、IBM SupportAssistantWorkbenchで提供されているガベージコレクションとメモリビジュアライザーを個人的に使用しています。キャプチャされたガベージコレクションの統計の概要と、アプリケーションのメモリがどのように動作しているかを確認するために使用できる動的グラフが提供されます。これでは、ヒープ上にあったオブジェクトはわかりません。

アプリケーションで問題が発生したときに、一時停止して生きることができる場合は、jmapコマンドを変更して次のようにします

jmap -dump:format=b,file=/file/location/dump.hprof <pid>

MATのようなツールを使用すると、すべてのオブジェクト、リークの容疑者、および世代、ヒープの参照に関するその他のさまざまな統計を確認できます。

チューニングディスカッション用に編集

起動パラメータに基づいて、試すことができることがいくつかあります

  • -Xmsを-Xmxと同じ値に設定します。これを行うことにより、JVMはより多くのヒープを割り当てるために時間を費やす必要がなくなります。アプリケーションに4GBがかかると予想される場合は、すぐにすべてを提供してください
  • このアプリケーションを実行しているシステム上のプロセッサの数に応じて、のフラグを設定できます -XX:ParallelGCThreads=##
  • 私はこれを試したことがありませんが、ドキュメントには、 -XX:+UseParallelOldGC古いGCコレクションの時間を短縮するためのいくつかの約束を示すパラメータが示されています。
  • 新世代のサイズをヒープの1/4に変更してみてください。(64ではなく1024)これは古い世代に過度の負担をかけている可能性があります。デフォルトのサイズは約30%で、若い世代に約2%を使用するようにアプリケーションを構成しています。最大サイズを設定していませんが、新しい世代が小さすぎてすべてのリクエストを処理できないため、古い世代に移動されるデータが多すぎるのではないかと心配しています。したがって、メモリをクリーンアップするには、より完全な(一時停止した)GCを実行する必要があります。

全体として、これだけのメモリを非常に高速に割り当てる場合は、メモリが古い世代に時期尚早に割り当てられるという世代の問題になる可能性があります。新しいgenサイズの微調整が機能しない場合は、-Xmx構成を介してヒープを追加するか、一歩下がってメモリに保持されているものを正確に見つける必要があります。前に説明したMATツールは、メモリ内のオブジェクトを保持している参照を表示できます。最初に箇条書き1と4を試すことをお勧めします。これは、正しい値を取得するための試行錯誤になります

于 2011-05-19T12:49:00.130 に答える