Javaメモリリークを見つける方法 質問する

Javaメモリリークを見つける方法 質問する

Java でメモリ リークを見つけるにはどうすればよいでしょうか (たとえば、JHat を使用)? 基本的な確認のために、JHat でヒープ ダンプをロードしようとしました。ただし、ルート参照 (参照) とか、何と呼ばれているかわかりません。基本的に、ハッシュ テーブル エントリ ([java.util.HashMap$Entry など) が数百メガバイトあることはわかりますが、マップはいたるところで使用されています... 大きなマップを検索する方法や、大きなオブジェクト ツリーの一般的なルートを見つける方法はありますか?

[編集] わかりました。これまでの回答を読みましたが、私はケチな人間だということだけ言っておきます (つまり、JProfiler にお金を払うよりも、JHat の使い方を学ぶことに興味があります)。また、JHat は JDK の一部なので、いつでも利用できます。もちろん、JHat ではブルート フォース以外に方法がないという場合を除きますが、そんなことはあり得ないと思います。

また、実際に変更することはできないと思います(ログの追加など)全てマップ サイズを変更し、リークに気付くまで十分な時間実行します。

ベストアンサー1

私は、Java のメモリ リークを見つけるために次のアプローチを使用しています。私は jProfiler を使用して大きな成果を上げましたが、グラフ作成機能 (差分はグラフ形式で分析する方が簡単) を備えた専門ツールであればどれでも機能すると思います。

  1. アプリケーションを起動し、すべての初期化が完了してアプリケーションがアイドル状態になる「安定」状態になるまで待ちます。
  2. メモリ リークが発生している疑いのある操作を複数回実行して、キャッシュや DB 関連の初期化が行われるようにします。
  3. GC を実行し、メモリのスナップショットを取得します。
  4. 操作を再度実行します。操作の複雑さと処理されるデータのサイズに応じて、操作を複数回実行する必要がある場合があります。
  5. GC を実行し、メモリのスナップショットを取得します。
  6. 2 つのスナップショットの diff を実行して分析します。

基本的に、分析は、たとえばオブジェクト タイプによる最大の正の差分から開始し、余分なオブジェクトがメモリ内に残る原因を見つける必要があります。

複数のスレッドでリクエストを処理する Web アプリケーションの場合、分析はより複雑になりますが、それでも一般的なアプローチが適用されます。

私はアプリケーションのメモリ フットプリントを削減することを特に目的としたプロジェクトを多数実施しましたが、アプリケーション固有の調整とトリックを組み合わせたこの一般的なアプローチは常にうまく機能しました。

おすすめ記事