1. ホーム
  2. java

[解決済み] Javaメモリリークの見つけ方

2022-05-10 11:56:30

質問

Javaで(例えばJHatを使って)メモリリークを見つけるにはどうしたらいいのでしょうか?私はJHatでヒープダンプをロードして、基本的なルックアップを試みました。しかし、私はルートリファレンスを見つけることができることになっている方法を理解していない ( レフ ) と呼ばれるものです。基本的に、数百メガバイトのハッシュテーブルのエントリ([java.util.HashMap$Entryとか)があることはわかるのですが、マップがあちこちに使われていて...。大きなマップを検索する方法、あるいは大きなオブジェクトツリーの一般的なルートを検索する方法はないでしょうか?

編集 OK、これまでの回答を読みましたが、私はケチな野郎だと言っておきましょう(JProfilerにお金を払うよりも、JHatの使い方を学びたいという意味です)。また、JHatはJDKの一部であるため、いつでも利用可能です。もちろん、ブルートフォース以外にJHatを使う方法がないのであれば話は別ですが、そんなことはあり得ないと思っています。

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

解決方法は?

私は、Javaのメモリリークを発見するために、次のような方法をとっています。私はjProfilerを使用して大きな成功を収めましたが、グラフ化機能(グラフィカルな形式で差分を分析するのが容易)を持つ任意の専門ツールが機能すると信じています。

  1. アプリケーションを起動し、すべての初期化が完了し、アプリケーションがアイドル状態になるまで、quot;stable" の状態になるまで待ちます。
  2. メモリリークが疑われる操作を数回実行し、キャッシュやDB関連の初期化を行わせる。
  3. GCを実行し、メモリスナップショットを取得します。
  4. 操作を再度実行します。操作の複雑さや処理されるデータの大きさによっては、操作を数回から数十回実行する必要がある場合があります。
  5. GCを実行し、メモリスナップショットを取得します。
  6. 2つのスナップショットに対してdiffを実行し、それを分析します。

基本的に解析は、例えばオブジェクトの種類による最大の正の差分から始まり、それらの余分なオブジェクトがメモリ上に固着する原因を見つける必要があります。

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

私は、アプリケーションのメモリフットプリントを削減することを目的としたプロジェクトを数多く手がけましたが、この一般的なアプローチにアプリケーション特有の微調整やトリックを加えることで、常にうまく機能しました。