Java OutOfMemory 例外をデバッグするにはどうすればよいですか?
-
12-10-2019 - |
質問
デバッグする最良の方法は何ですか java.lang.OutOfMemoryError
例外は?
これがアプリケーションで発生すると、アプリケーション サーバー (Weblogic) はヒープ ダンプ ファイルを生成します。ヒープダンプファイルを使用する必要がありますか?Java スレッド ダンプを生成する必要がありますか?違いは何ですか?
アップデート:スレッド ダンプを生成する最良の方法は何ですか?は kill -3
(私たちのアプリは Solaris 上で実行されます) アプリを強制終了してスレッド ダンプを生成する最良の方法は何ですか?アプリを強制終了せずにスレッド ダンプを生成する方法はありますか?
解決
Javaのメモリ外エラーの分析と修正は非常に簡単です。
Javaでは、メモリを占有するオブジェクトはすべて他のオブジェクトにリンクされており、巨大な木を形成します。アイデアは、ツリーの最大の枝を見つけることです。これは通常、メモリリークの状況を指します(Javaでは、オブジェクトを削除するのを忘れないときではなく、オブジェクトを忘れない場合、つまり、どこかに参照)。
ステップ1.実行時にヒープダンプを有効にします
でプロセスを実行します -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp
(これらのオプションを常に有効にすることは安全です。必要に応じてパスを調整します。Javaユーザーが手紙を作成する必要があります)
ステップ2.エラーを再現します
アプリケーションをまで実行します OutOfMemoryError
発生します。
JVMは、ようなファイルを自動的に書き込みます java_pid12345.hprof
.
ステップ3.ダンプを取得します
コピー java_pid12345.hprof
PCに
ステップ4. IBMを使用してダンプファイルを開きます ヒープアナライザー またはEclipse's メモリアナライザー
ヒープアナライザーは、エラー時に生きていたすべてのオブジェクトのツリーを提示します。それはあなたを指し示す可能性があります 直接 それが開くときの問題で。
注:ダンプ全体をロードする必要があるため、Heapanalyzerに十分なメモリを与えてください!
java -Xmx10g -jar ha456.jar
ステップ5.最大のヒープ使用の領域を特定します
オブジェクトの木を閲覧し、不必要に保持されているオブジェクトを識別します。
それも起こる可能性があることに注意してください すべて オブジェクトの必要が必要です。つまり、より大きなヒープが必要です。サイズと 曲 ヒープ 適切に.
ステップ6.コードを修正します
実際に必要なオブジェクトのみを維持するようにしてください。タイムリーにコレクションからアイテムを削除します。もはや必要ないオブジェクトへの参照を保持しないようにしてください。
他のヒント
の組み合わせを使用して成功しました Eclipse Memory Analyzer(MAT) と Java Visual VM ヒープダンプを分析します。 MATには、コード内の努力をどこに集中させるかという一般的なアイデアを提供することを実行できるというレポートがいくつかあります。 VisualVMには、検査に興味があるさまざまなオブジェクトの内容を実際に検査するためのより良いインターフェイス(私の意見)があります。特定のクラスのすべてのインスタンスを表示し、それらが参照されている場所と自分自身を参照するものを確認できるフィルターがあります。どちらかのツールを使用してからしばらく経ちます。その時点で両方を使用して、私のためにうまくいきました。
一般的にデバッグすることは非常に困難です OutOfMemoryError
問題。プロファイリングツールを使用することをお勧めします。 JProfilerはかなりうまく機能します。私は過去にそれを使用しましたが、非常に役立つかもしれませんが、少なくとも同じくらい良いものがあると確信しています。
あなたの具体的な質問に答えるには:
ヒープダンプは、ヒープ全体の完全なビュー、つまりで作成されたすべてのオブジェクトの完全なビューです new
. 。あなたが記憶を使い果たした場合、これはかなり大きくなります。それはあなたが持っている各タイプのオブジェクトの数をあなたに示します。
スレッドダンプには、各スレッドのスタックが表示され、ダンプの時点で各スレッドがどこにあるかが表示されます。それを覚えておいてください どれか スレッドはJVMがメモリを使い果たした可能性がありますが、実際にエラーをスローする別のスレッドである可能性があります。たとえば、スレッド1は、利用可能なすべてのヒープスペースを埋めるバイト配列を割り当て、スレッド2で1バイト配列を割り当ててエラーをスローします。
jmap/jhat を使用して、実行中の Java プロセスに接続することもできます。これらのツール (ファミリー) は、実際に実行中のアプリケーションをデバッグする必要がある場合に非常に役立ちます。
jmap をファイルにログインする cron タスクとして実行したままにして、後で分析できるようにすることもできます (これは、ライブ メモリ リークをデバッグするのに役立つことがわかっています)。
jmap -histo:live <pid> | head -n <top N things to look for> > <output.log>
Jmap は、-dump オプションを使用してヒープ ダンプを生成するために使用することもできます。このダンプは、jhat を通じて読み取ることができます。
詳細については、次のリンクを参照してくださいhttp://www.lshift.net/blog/2006/03/08/java-memory-profiling-with-jmap-and-jhat
ここにブックマークへの別のリンクがありますhttp://java.sun.com/developer/technicalArticles/J2SE/monitoring/
デバッグする最良の方法は何ですか
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クラスのメタデータ(Virtual Machines interning in java classの内部プレゼンテーション)は、ネイティブメモリで割り当てられています(ここではmetaspaceと呼ばれます)
java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?
:
原因: 詳細なメッセージ「理由のためにサイズバイトを要求します。スワップスペースから?」のように見えます OutOfMemoryError
例外。ただし、Java Hotspot VMコードは、ネイティブヒープからの割り当てが失敗し、ネイティブヒープが疲労に近い場合がある場合、この明らかな例外を報告しています。
java.lang.OutOfMemoryError: Compressed class space
原因: 64ビットプラットフォームでは、クラスメタデータへのポインターは、32ビットオフセット(UseCompressedoopsを使用)で表すことができます。これは、コマンドラインフラグUseCompredessClassPointers(デフォルトで)によって制御されます。
場合 UseCompressedClassPointers
使用されている場合、クラスメタデータで利用可能なスペースの量は量に固定されています CompressedClassSpaceSize
. 。必要なスペースの場合 UseCompressedClassPointers
超えて CompressedClassSpaceSize
, 、a java.lang.OutOfMemoryError
詳細な圧縮クラススペースがスローされます。
ノート: クラスメタデータと他のメタデータのクラスメタデータは複数あります。 Klassメタデータのみが、境界のある空間に保存されます CompressedClassSpaceSize
. 。他のメタデータはMetaspaceに保存されます。
ヒープダンプファイルを使用する必要がありますか? Javaスレッドダンプを生成する必要がありますか?違いは何ですか?
はい。このヒープヒープダンプファイルを使用して、プロファイリングツールを使用して問題をデバッグできます VisualVM また マットスレッドダンプを使用して、スレッドのステータスに関するさらなる洞察を得ることができます。
この質問を参照して、違いを知ります。
WebSphereのJavacore、Thread Dump、Heap Dumpの違い
スレッドダンプを生成する最良の方法は何ですか? Kill -3(私たちのアプリはSolarisで実行されています)は、アプリを殺してスレッドダンプを生成する最良の方法ですか?スレッドダンプを生成しますが、アプリを殺さない方法はありますか?
kill -3 <process_id>
スレッドダンプを生成すると、このコマンドはJavaプロセスを殺しません。
IBMは、これらのヒープダンプを分析するためのツールを提供しているようです。 http://www.alphaworks.ibm.com/tech/heaproots ;もっと http://www-01.ibm.com/support/docview.wss?uid=swg21190476 .
ヒープダンプを見るためのツールを取得したら、スレッドスタック内の実行状態にあるスレッドを確認します。おそらくエラーが発生したものの1つです。ヒープダンプが上部にエラーがあるスレッドがあることを教えてくれる場合があります。
それはあなたを正しい方向に向けるはずです。次に、標準のデバッグ技術(ロギング、デバッガなど)を使用して、問題を把握します。ランタイムクラスを使用して、現在のメモリ使用量を取得し、問題のメソッドまたはプロセスの実行としてログを記録します。
私は通常、Eclipseメモリアナライザーを使用しています。疑わしい犯人(ヒープダンプのほとんどを占有しているオブジェクト)と、それらのオブジェクトを生成している異なるコール階層を表示します。そのマッピングがあったら、コードに戻って、コードパスのどこにいてもメモリリークがあるかどうかを理解しようとします。
ただし、OOMは常にメモリリークがあることを意味するとは限りません。ハードウェア/VMでは、安定した状態または荷重下のアプリケーションが必要とするメモリが利用できない可能性があります。たとえば、VMのように32ビットJavaプロセス(最大メモリは〜4GB)がある可能性があります。そのような場合、最初はアプリケーションが正常に実行される可能性がありますが、OOMはメモリ要件が3GBに近づいたときに遭遇する可能性があります。
他の人が述べたように、スレッドダンプをキャプチャするのは費用はかかりませんが、ヒープダンプをキャプチャするのはです。ヒープダンプアプリケーションをキャプチャしながら(一般的に)フリーズし、それに続く再起動のみが回復するのに役立つことを観察しました。