18

java.lang.OutOfMemoryError例外をデバッグする最良の方法は何ですか?

これがアプリケーションで発生すると、アプリケーション サーバー (Weblogic) がヒープ ダンプ ファイルを生成します。ヒープ ダンプ ファイルを使用する必要がありますか? Java スレッド ダンプを生成する必要がありますか? 違いは正確には何ですか?


更新: スレッド ダンプを生成する最良の方法は何ですか? (私kill -3たちのアプリは Solaris で実行されます) アプリを強制終了してスレッド ダンプを生成する最良の方法はありますか? アプリを強制終了せずにスレッド ダンプを生成する方法はありますか?

4

8 に答える 8

7

Eclipse Memory Analyzer (MAT)Java Visual VMを組み合わせてヒープ ダンプを分析することに成功しました。MAT には、実行できるレポートがいくつかあります。これにより、コード内のどこに注力すべきかについての一般的なアイデアが得られます。VisualVM には、調べたいさまざまなオブジェクトの内容を実際に調べるためのより優れたインターフェイスがあります (私の意見では)。特定のクラスのすべてのインスタンスを表示し、それらが参照されている場所とそれらが参照しているものを確認できるフィルターがあります。これにどちらのツールも使用してからしばらく経ちましたが、現在はより近い機能セットを備えている可能性があります。当時、両方を使用するとうまくいきました。

于 2010-12-22T18:55:46.340 に答える
5

java.lang.OutOfMemoryError例外をデバッグする最良の方法は何ですか?

メッセージのOutOfMemoryError説明でエラーの種類を説明します。例外を処理するには、エラー メッセージの説明を確認する必要があります。

メモリ不足の例外にはさまざまな根本原因があります。詳細については、Oracle のドキュメントページを参照してください。

java.lang.OutOfMemoryError: Java heap space:

原因: Java ヒープ領域の詳細メッセージは、Java ヒープにオブジェクトを割り当てることができなかったことを示しています。

java.lang.OutOfMemoryError: GC Overhead limit exceeded:

原因:詳細メッセージ「GC オーバーヘッド制限を超えました」は、ガベージ コレクターが常に実行されており、Java プログラムの進行が非常に遅いことを示しています。

java.lang.OutOfMemoryError: Requested array size exceeds VM limit:

原因: 詳細メッセージ「要求された配列サイズが VM 制限を超えています」は、アプリケーション (またはそのアプリケーションで使用される API) がヒープ サイズより大きい配列を割り当てようとしたことを示しています。

java.lang.OutOfMemoryError: Metaspace:

原因: Java クラス メタデータ (Java クラスの仮想マシン内部プレゼンテーション) がネイティブ メモリ (ここではメタスペースと呼ばれます) に割り当てられています。

java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?:

原因:詳細メッセージ「request size bytes for reason.Out of swap space?」はOutOfMemoryError例外のようです。ただし、Java HotSpot VM コードは、ネイティブ ヒープからの割り当てが失敗し、ネイティブ ヒープがほぼ枯渇している可能性がある場合に、この明らかな例外を報告します。

java.lang.OutOfMemoryError: Compressed class space

原因: 64 ビット プラットフォームでは、クラス メタデータへのポインタを 32 ビット オフセットで表すことができます (UseCompressedOops を使用)。これは、コマンド ライン フラグ UseCompressedClassPointers (デフォルトでオン) によって制御されます。

を使用する場合、UseCompressedClassPointersクラス メタデータに使用できる容量は amount に固定されCompressedClassSpaceSizeます。に必要なスペースが をUseCompressedClassPointers超えた場合CompressedClassSpaceSizejava.lang.OutOfMemoryErrordetail Compressed クラス スペースがスローされます。

注:クラス メタデータには複数の種類があります (klass メタデータとその他のメタデータ)。で囲まれたスペースには、klass メタデータのみが格納されCompressedClassSpaceSizeます。他のメタデータは Metaspace に保存されます。

ヒープ ダンプ ファイルを使用する必要がありますか? Java スレッド ダンプを生成する必要がありますか? 違いは正確には何ですか?

はい。このヒープ ヒープ ダンプ ファイルを使用して、visualvmmatなどのプロファイリング ツールを使用して問題をデバッグ できます。スレッド ダンプを使用して、スレッドのステータスに関する詳細な洞察を得ることができます。

違いを知るには、この SE の質問を参照してください。

Websphere での javacore、スレッド ダンプ、ヒープ ダンプの違い

スレッド ダンプを生成する最良の方法は何ですか? kill -3 (私たちのアプリは Solaris で実行されます) は、アプリを強制終了してスレッド ダンプを生成するための最良の方法ですか? アプリを強制終了せずにスレッド ダンプを生成する方法はありますか?

kill -3 <process_id>スレッド ダンプを生成し、このコマンドは Java プロセスを強制終了しません。

于 2016-05-19T15:32:20.950 に答える
3

一般に、問題をデバッグすることは非常に困難OutOfMemoryErrorです。プロファイリングツールを使用することをお勧めします。JProfiler はかなりうまく機能します。私は過去にそれを使用したことがあり、非常に役立つ可能性がありますが、少なくとも同じくらい優れているものは他にもあると確信しています.

特定の質問に答えるには:

ヒープ ダンプは、ヒープ全体、つまり で作成されたすべてのオブジェクトの完全なビューですnew。メモリが不足している場合、これはかなり大きくなります。各タイプのオブジェクトがいくつあるかを示します。

スレッド ダンプには、各スレッドのスタックが表示され、ダンプ時に各スレッドがコード内のどこにあるかが示されます。任意のスレッドがJVM のメモリ不足を引き起こす可能性がありますが、実際にエラーをスローするのは別のスレッドである可能性があることに注意してください。たとえば、スレッド 1 が使用可能なすべてのヒープ領域を埋めるバイト配列を割り当てた後、スレッド 2 が 1 バイトの配列を割り当てようとしてエラーをスローします。

于 2010-12-22T18:08:55.673 に答える
3

jmap/jhat を使用して、実行中の Java プロセスにアタッチすることもできます。これらの (ファミリの) ツールは、ライブ実行中のアプリケーションをデバッグする必要がある場合に非常に役立ちます。

また、jmap を cron タスクとして実行し、後で分析できるファイルにログインすることもできます (ライブ メモリ リークをデバッグするのに役立つことがわかっています)。

jmap -histo:live <pid> | head -n <top N things to look for> > <output.log>

Jmap は、jhat を介して読み取ることができる -dump オプションを使用してヒープ ダンプを生成するためにも使用できます。

詳細については、次のリンクを参照してください http://www.lshift.net/blog/2006/03/08/java-memory-profiling-with-jmap-and-jhat

ブックマークへの別のリンクは次のとおりです http://java.sun.com/developer/technicalArticles/J2SE/monitoring/

于 2010-12-22T20:43:52.123 に答える
2

IBM は、これらのヒープ ダンプを分析するためのツールを提供しているようです: http://www.alphaworks.ibm.com/tech/heaproots ; 詳細はhttp://www-01.ibm.com/support/docview.wss?uid=swg21190476を参照してください。

于 2010-12-22T18:09:41.960 に答える
1

ヒープ ダンプを確認するためのツールを入手したら、スレッド スタックで Running 状態だったスレッドを確認します。おそらくエラーが発生したものの1つです。場合によっては、ヒープ ダンプによって、どのスレッドの一番上でエラーが発生したかがわかります。

それはあなたを正しい方向に向けるはずです。次に、標準のデバッグ手法 (ロギング、デバッガーなど) を使用して、問題に焦点を合わせます。Runtime クラスを使用して、現在のメモリ使用量を取得し、問題のメソッドまたはプロセスの実行時にログに記録します。

于 2010-12-22T18:29:03.200 に答える
1

私は通常、Eclipse Memory Analyzer を使用します。疑わしい原因 (ヒープ ダンプの大部分を占めているオブジェクト) と、それらのオブジェクトを生成しているさまざまな呼び出し階層が表示されます。マッピングが完了したら、コードに戻り、コード パスのどこかにメモリ リークの可能性があるかどうかを理解しようとします。

ただし、OOM は常にメモリ リークがあることを意味するわけではありません。安定した状態または負荷がかかっているときに、アプリケーションが必要とするメモリがハードウェア/VM で利用できない可能性は常にあります。たとえば、32 ビットの Java プロセス (使用される最大メモリは ~ 4GB) が存在する可能性がありますが、VM には 3 GB しかありません。このような場合、最初はアプリケーションが正常に動作する可能性がありますが、メモリ要件が 3GB に近づくと OOM が発生する可能性があります。

他の人が述べたように、スレッド ダンプのキャプチャはコストがかかりませんが、ヒープ ダンプのキャプチャはコストがかかります。ヒープ ダンプ アプリケーションのキャプチャ中に (一般的に) フリーズし、kill とそれに続く再起動のみが回復に役立つことを確認しました。

于 2015-05-05T16:37:10.403 に答える