![]() ![]() ![]() ![]() |
Java アプリケーションは、さまざまな原因で動作を停止する場合があります。当然のことながら、最も一般的な原因は、アプリケーションの動作が完了したこと、または正常に中断したことです。その他の原因としては、Java アプリケーション エラー、未処理の例外または OutOfMemoryError などの回復できない Java エラーが考えられます。場合によっては、JVM 自体で正常に回復できなかった問題が起きたことを意味する JVM クラッシュが発生する可能性があります。クラッシュが発生した場合に Oracle JRockit JVM が出力するダンプ情報から、JVM クラッシュを特定することができます。
このドキュメントでは、JVM のクラッシュを診断し、解決する方法を説明します。内容は以下のとおりです。
Oracle とのサポート契約がない場合でも、JRockit JVM で問題が発生した場合は、Oracle サポートまでご連絡ください。連絡をいただくと、Oracle では次回のリリースでその問題が修正されていることを確認できます。Oracle サポートへの連絡方法については、「Oracle サポートへのトラブル レポートの送付」を参照してください。
JVM クラッシュの診断と解決の第一段階は、クラッシュの分類です。たとえば、クラッシュが発生した場所および原因を特定します。
JRockit JVM はクラッシュすると、クラッシュした時点でのコンピュータと JVM プロセスの状態のスナップショットを作成し、その情報を次のいずれかの「クラッシュ ファイル」に書き込みます。
dump
ファイル : dump
ファイルは、クラッシュした時点でのフル メモリ イメージおよび JVM が動作していた環境の概要を示すテキスト ファイルです。このファイルは、クラッシュ時に JVM 自身によって作成されます。クラッシュの種類を調べるのに使用できるほか、場合によっては修復済みの問題の特定に使用できることもあります。このファイルから、問題の原因を正確に特定するための十分な情報が得られることはほとんどありません。core
ファイルは、「クラッシュ ファイルの概要」で説明されているとおり、バイナリ クラッシュ ファイルです。デフォルトでは、クラッシュした時点での、JVM プロセス全体の完全なコピーです。core
ファイルは Linux や Solaris などの Unix 系システムで作成されます。core
ファイルのファイル名は、通常、<pid>.core
という形式です。mdmp
ファイル (ミニダンプ ファイル): windows 版の core ファイルです。
バイナリ クラッシュ ファイル (Core
ファイルと mdmp
ファイル) は、Oracle サポートが JRockit JVM の問題を解決するのに非常に役に立ちます。ただし、Oracle システムとサービス契約を結んでいないと、これらのファイルはあまり役に立ちません。
テキスト dump
ファイルを取得し、クラッシュの種類を示す情報について確認することで、クラッシュが発生した場所と原因を特定できる場合があります。オペレーティング システムのセットアップのチェックに加えて、バイナリ dump ファイルのサイズをチェックすることが、役に立つ場合があります。表 30-1 に、発見可能な兆候と、それらの兆候に対応する、予想されるクラッシュの種類を示します。
core ファイルまたは mdmp ファイルのサイズが、その OS におけるプロセスの仮想メモリ サイズの最大値に近い値になっています。詳細については、「クラッシュ ファイルの概要」を参照してください。
|
|
JVM は、Java ヒープ、Java メソッド、スレッド スタックおよび JVM 内部データ構造など、さまざまな目的で仮想メモリを確保します。さらに、ネイティブ (JNI) コードでも、メモリを割り当てることができます。プロセス サイズは、JVM によって確保されたすべてのメモリから構成され、オペレーティング システムの制限に応じて制限されます。JVM プロセスの仮想メモリの割り当てがこれらの制限を超えると、JVM で仮想メモリが不足し、クラッシュが発生する可能性があります。この節では、以下のトピックを取り上げます。
仮想メモリ不足エラーのデバッグを開始する前に、まず、エラーが本当に JVM プロセスでの仮想メモリ不足によるものであるのかを確認する必要があります。この節では、以下の情報について説明します。
表 30-2 にビットの各種オペレーティング システムで使用可能な仮想メモリの最大値を示します。64 ビットのプラットフォームでは、仮想メモリは実質的に無制限です。
テキスト dump
ファイルは、JVM によって作成された場合、メモリの割り当てに失敗したことを示す可能性があります。詳細については、「クラッシュ ファイルの概要」を参照してください。これは、JVM プロセスで仮想メモリが不足していることを顕著に示しています。
JRockit JVM がクラッシュすると、バイナリ クラッシュ ファイルが生成されます。デフォルトでは、このファイルには JVM プロセス全体のコピーが含まれます。このファイルのサイズをチェックして、JVM プロセスで本当に仮想メモリが不足しているかどうかを判断してください。
-XXdumpSize
またはオペレーティング システム コマンドの ulimit
(Linux および Solaris のみ) を使用して制限されていないことを確認します。コマンド ulimit -a
を使用して、Linux および Solaris でクラッシュ ファイルのサイズが無制限であることを確認してください。バイナリ クラッシュ ファイルのサイズが制限されていると、このコマンドを使用して JVM プロセスで仮想メモリが不足しているかどうかを確認できません。mdmp
または core
ファイルのサイズをヒープと比較し、ヒープのサイズよりも大きいことを確認します。これは、バイナリ クラッシュ ファイルが、ディスク領域の制限などによって切り捨てられていないことを確認するためのサニティ チェックです。mdmp
または core
ファイルのサイズが特定の OS によって許可されているプロセスの最大サイズに近づいているかどうかを判断します。
JVM プロセスで仮想メモリが不足していることを確認したら、問題を解決するためのトラブルシューティングを開始できます。この節では、以下のトピックを取り上げます。
最新の JRockit JVM リリースを実行していることを確認してください。JVM のメモリ使用の問題を解決したり、使用量を減らしたりする修正プログラムが数多く作成されています。主要な JDK に最新バージョンの JVM を使用すれば、メモリ効率が最も高くなります。
Java ヒープは、JVM で使用されるメモリの合計の一部に過ぎません。Java ヒープが大き過ぎると、Java メソッドがコンパイルおよび最適化される際、またはネイティブ ライブラリが読み込まれる際に、JVM が起動できないか、または仮想メモリが不足する場合があります。このような状況が発生する場合、最大ヒープ サイズの設定を下げてみる必要があります。
Windows 2000 Advances Server および Datacenter、Windows 2003 および Windows XP では、BOOT.INI で /3GB オプションを指定してオペレーティング システムを起動するオプションがあります。このオプションを指定すると、最大仮想メモリ プロセス サイズは 2GB から 3GB に変更されます。
使用している JNI コードにメモリ リークがないかをチェックします。JNI コードが適切に記述または使用されていないと、メモリ リークが発生する場合があります。これにより、プラットフォームでの仮想メモリの最大サイズに達するまで、Java プロセスが増大します。
仮想メモリの使用状況を記録すると、メモリ使用量の増加が確認できるため、仮想メモリ不足の問題を識別し、診断するのに役立ちます。この節では、以下について、仮想メモリの使用状況の統計を集める方法を説明します。
Windows ツールの perfmon を使用して、PrivateBytes プロセス カウンタを記録します。JVM プロセスで予約された仮想メモリの量に関する情報を収集してください。次の手順に従います。
仮想メモリの使用状況を、一定の間隔で記録するためのスクリプトを作成します。以下に例を示します。
top -b -n 10 > virtualmemory.log
このスクリプトは 10 秒おきに「top
」を実行し、そのデータを virtualmemory.log
ファイルに記録します。実行中の全プロセスの仮想メモリ使用量が、このファイルの VIRT 列に記録されます。現在の状態だけを確認するには、top
と入力して〔Shift〕+〔M〕を押し、出力をメモリ使用量でソートします。これで、通常は JVM プロセスが出力の一番上に並びます。
Virtualmemory.log
のような記録を作成すると、JRockit JVM プロセスによってメモリ使用量が実際に増加していることを確認でき、それを BEA サポートに証拠として提示できるので便利です。
以上の方法で問題が解決しない場合は、Oracle サポートにお問い合わせいただく必要があります。提供する必要のある情報と送付方法の詳細については、「Oracle サポートへのトラブル レポートの送付」を参照してください。
スタック オーバーフローのクラッシュは、JRockit JVM がスタック オーバーフローのエラーを適切に処理できない場合に起こります。J2se javadoc によると、java.lang.stackoverflowerror
が「適切に」処理されるとは、java.lang.VirtualMachineError
を送出して、「java 仮想マシンが壊れているか、処理を続けるために必要なリソースが不足していることを示す」ことです。詳細については、以下の J2SE java.lang
Javadoc を参照してください。
JRockit JVM R26 (およびそれ以降) のダンプ ファイルには、送出されたスタック オーバーフロー エラーの数について情報が記録されます。
スタック オーバーフローのクラッシュは、テキスト dump
ファイルの一番上のあたりに「Error Message: Stack overflow
」と表示されるので簡単に特定できます。その他にも、クラッシュ ファイルのスタック トレースが極度に長い場合や、逆にスタック トレースがまったくない場合に、スタック オーバーフローのクラッシュである可能性があります。dump ファイルに「StackOverFlow: 2 StackOverFlowErrors occured
」のように表示されている場合は、以前のスタック オーバーフローの問題によりクラッシュがトリガされた可能性があります。
この節では、スタック オーバーフロー エラーの解決方法をいくつか説明します。
スタック オーバーフロー エラーの主な原因に、JRockit JVM のメモリ制限を超えたスタック領域を使用するようにアプリケーションが作成されていることがあります。.dump
ファイルでスタック トレースを確認し、スタック領域の使用量を減らすように Java コードを変更できないか調べてください。
アプリケーションのスタック領域の使用量を変えるのが不可能な場合は、JVM の起動時に -Xss
オプションを使用して、スレッドのスタックサイズを変更することができます。以下に例を示します。
-Xss:<value>
[k|m]
-Xcheckedstacks を使用すると、JRockit JVM のスタック オーバーフロー エラーに対する抵抗力を強化できます。これによって、通常は JVM がダンプしなくなり、java.lang.StackOverflowError
を送出しなくなります。このオプションを指定すると、JVM がスタック上のページにアクセスするので、パフォーマンスがやや低下します。
JRockit JVM を Linux で実行中にアプリケーションがクラッシュした場合は、linux コンフィグレーションがサポート対象でないことが原因である可能性があるので、スタック トレースにクラッシュの理由が示されていても、サポート対象の Linux コンフィグレーションで実行しているかを確認する必要があります。以下を確認してください。
JRockit JVM は、OS ベンダから提供される汎用の製品をサポートしますが、カスタム ビルドのカーネルはサポートしません。お使いの linux のバージョンがサポート対象かどうかを調べるには、「Oracle JRockit でサポート対象のコンフィグレーション」で BEA JRockit の該当するバージョンの節を参照してください。
IA32 の Linux では、i686 アーキテクチャ用にコンパイルされた glibc を使用するように設定される必要があります。そうでない場合は、BEA JRockit がハングし、クラッシュが起こります。
どの glibc がインストールされているかをチェックするには、以下を実行します。
rpm -q --queryformat '\n%{NAME} %{VERSION} %{RELEASE} %{ARCH}\n' glibc
たとえば次のように、この出力に「i386」のように表示される場合は、
サポート対象でない glibc を使用しています。glibc のバージョンを、「i386」と表示されないものにアップグレードする必要があります。サポート対象のシステムからの出力の例を以下に示します。
glibc 2.3.4 2.25 i686
コア ファイルが gdb にある場合は、次のコマンドを実行することによって、どのスレッド ライブラリを使用しているかに関してヒントを得ることができます。
info shared
ロードされた libpthread<x>.so
のパスを確認してください。
/lib/
下にある場合は、rpm コマンドの結果を調べる必要があります。この出力に「i386」のように書かれている場合は、サポート対象でない glibc を使用しているので、glibc のバージョンをアップグレードする必要があります。
JVM クラッシュは、JRockit JVM のプログラミング エラーによって発生します。JVM クラッシュを特定およびトラブルシューティングすることで、JRockit JVM で問題が解決されるまでの一時的な回避策を見つけることができます。また、これにより、Oracle サポートが問題を迅速に特定し解決できるようになる場合があります。
この節では、コード生成のクラッシュを特定およびトラブルシューティングする方法について説明します。内容は以下のとおりです。
コード生成のクラッシュの最も一般的な原因は、コンパイルに失敗したメソッドです。JRockit JVM がメソッドのコンパイルに失敗すると、JVM がクラッシュするか、メソッドがソース コードに書かれている以外の処理を実行します。コードの生成中に JVM がクラッシュした場合、クラッシュ時にどのメソッドをコンパイルしていたかをテキスト dump
ファイルから特定できます。これを調べるには、ファイルの上の方から Method
: で始まる行を探します。
どのメソッドが原因で問題が起きているかを知ることが、問題解決のための最初のステップです。
JRockit JVM がメソッドのコンパイルに失敗している場合、その原因はおそらく JVM のコンパイラによる最適化です。最適化が原因かどうかを調べるには、-XnoOpt
コマンドライン オプションを指定してアプリケーションを再起動し、最適化を無効にします。次に例を示します。
java-XnoOpt
myApp
プログラムが JRockit JVM で正常に実行されれば、問題の原因はコードの最適化です。
最適化を無効にして JRockit JVM のクラッシュを防止したら、次に、問題のあるメソッドを最適化から除外してみてください。そのメソッドだけを最適化から除外できれば、ほとんどの最適化を有効にしたままでアプリケーションを実行できる場合があります。それでも問題が解決しない場合は、Oracle サポートに連絡してください。または、起動時に -xxpreopt
コマンドを指定して、常に最適化コンパイラを使用するようにしてみてください (最適化コンパイラを常に使用すると、JVM の起動が遅くなる可能性があります)。
特定のメソッドを最適化から除外するには opt ファイルを使用します。問題のあるメソッドを最適化せずにアプリケーションが正しく実行された場合は、この方法で問題を解決できます。
opt ファイルは 1 文字のコードであるディレクティブが記述されたテキスト ファイルです。ディレクティブはオプティマイザに特定のメソッドを最適化しないという指示や、必ず最適化するという指示を出します。Opt ファイルを作成したら、-djrockit.optfile=<
filename
>
プロパティ (<
filename
>
は opt ファイル) を使用して、opt ファイルの名前と場所を指定することができます。
コード リスト 30-1 に、このファイルの内容を示します。
- java/lang/FloatingDecimal.dtoa
- java/lang/Object
- sun/awt/windows/WComponentPeer.set*
コード リスト 30-1 で、最初の 2 行の先頭にある「-
」は、最適化コンパイラがこのメソッドを最適化しないことを指定しています。したがって、この例では「-
」ディレクティブによって、以下のメソッドを最適化しないことがオプティマイザに指示されます。
注意 : | R26.4 よりも前のバージョンの JRockit JVM を使用している場合、「- 」を使用しても、メソッドの再生成は完全には無効になりません。仮にメソッド m に「- 」を指定し、hotspot ディテクタがそれを hotspot であると認識した場合、そのメソッドは再生成されますが、最適化はされません。 |
「-
」だけがこの回避策で使用できるディレクティブです。この他にも h
(メソッドに対して Hotspot ディテクタによる最適化を行うが、事前の最適化は行わない)、p
(メソッドに対して事前の最適化を行い、Hotspot ディテクタによる最適化を行わない)、+
(メソッドに対して事前の最適化と Hotspot ディテクタによる最適化を行う) などのディレクティブはありますが、この回避策では使用できません。
opt ファイルが期待どおりに機能していることを確認するには、-Xverbose:opt
を使用して出力をチェックします。除外したメソッドは表示されないはずです。
Ctrl-Break ハンドラを使って opt ファイルを設定することもできます。このハンドラの名前は run_optfile
です。正式な opt ファイルを <
filename
>
引数として受け取ります。以下に例を示します。
run_optfile optfile=<
filename
>
ctrl-break
は押した場合は、“-
”にマッチングするすべてのメソッドは、optfile でディレクティブする最適化されません。
クラッシュの原因がコンパイルに失敗したメソッドではないとわかり、外部のインスツルメンテーション ツール (JProbe や OptimizeIt など) を使用している場合は、このツールが問題の原因でないか調査するとよい場合があります。これらのツールはバイトコードを書き換えることがあり、予期しない動作の原因となる可能性があります。場合によってはツールに直接の問題があることも考えられますが、JRockit JVM が抱える問題によってツールがクラッシュを起こしているケースもあります。クラッシュの原因からツールを除外するには、ツールを無効にしてアプリケーションを再実行します。それでもクラッシュが起きる場合は、インスツルメンテーション ツールが原因ではありません。アプリケーションが正常に実行される場合は、別のツールを使用するか、ツールを使わずに実行する必要があります。
Opt ファイルの回避策でも問題が軽減しない、または問題のあるメソッドを最適化せずにアプリケーションを正常に実行することができない場合は、Oracle サポートにお問い合わせいただく必要があります。Oracle に問題を報告する方法、およびその際に提出する情報については、「Oracle サポートへのトラブル レポートの送付」を参照してください。
コード生成のクラッシュの場合、Oracle サポートに以下のデータを提示していただく必要があります。
この節では、ガベージ コレクションのクラッシュを特定およびトラブルシューティングする方法について説明します。内容は以下のとおりです。
テキスト dump
ファイルのスタック トレースを調べることで、ガベージ コレクションのクラッシュを特定できます。スタック トレースにガベージ コレクション関数がある場合、またはクラッシュの原因となったスレットがガベージ コレクション スレッドの 1 つである場合、クラッシュがガベージ コレクション中に発生した可能性が最も高くなります。スタック トレース内のガベージ コレクション関数は、mm
、gc
、yc
、および oc
などのプレフィックスで識別されます。
ガベージ コレクションのクラッシュが発生した場合、最も簡単で最も推奨される解決方法は、JRockit JVM を最新のバージョンにアップグレードすることです。問題を細かく診断すると、非常に複雑で大変な時間がかかることがあります。最新バージョンの JVM ではその問題が修正されている場合があるため、アップグレードすると問題を回避できる可能性があります。
JVM を最新のバージョンにアップグレードしない (できない) 場合、または既に最新バージョンの JVM を使用している場合は、以下のいずれかの方法でガベージ コレクションのクラッシュを回避できないか試してください。
使用中のガベージ コレクタにバグがあり、別のガベージ コレクタに変えることでバグを回避できる場合があります。ただし、コレクタを変更すると、Oracle JRockit JVM から同じパフォーマンス プロファイルを得られなくなります。
確定的ガベージ コレクションを使用している場合、別のガベージ コレクタに変えることはできません。確定的ガベージ コレクションの機能を保持する必要があります。ガベージ コレクタを変える代わりに、Oracle サポートに問い合わせてください。
-Xgcprio:throughput
で問題がある場合は、-Xgc:parallel
に切り替えてみる。-Xgcprio:pausetime
で問題がある場合は、-Xgc:gencon
または -Xgc:singlecon
に切り替えてみる。-Xgc:singlecon
を使用している場合は、-Xgc:gencon
または -Xgc:singlepar
に切り替えてみます。-Xgc:singlecon
)-Xgc:singlepar
または -Xgc:parallel
)-Xgc:gencon
)-Xgc:genpar
)
静的なガベージ コレクタの使用の詳細については、「静的なガベージ コレクション方式を選択する」を参照してください。
ヒープを圧縮のバグにより、ガベージ コレクションのクラッシュの原因となる問題が発生する場合があります。圧縮を無効にするには、起動時に -XXnoCompaction
を設定します。ただし、このオプションを使用するとヒープが断片化するおそれがあるため、トラブルシューティングを行う場合にのみ使用してください。ヒープが断片化されすぎると、メモリ不足エラーが発生するおそれがあります。
誤ったインライン化によってコードが壊れ、それが原因でガベージ コレクタが生存しているオブジェクトを追跡できなくなる場合があります。インライン化を無効にするには、コマンドライン オプションを組み合わせて -XXnoJITInline -XnoOpt
のように指定します。このようにオプションを 2 つ使う必要があるのは、-XXnoJITInline
はメソッドが最初にコンパイルされるときのみインライン化を無効にするからです。一緒に -XnoOpt
を設定しなければ、コードが最適化されるときにメソッドがインライン化される可能性があります。
注意 : | -XnoOpt (-XXnoJITInline なし) で問題が解決した場合は、コードの最適化が問題の原因かもしれません。逆に、-XXnoJITInline (-xnoopt なし) で問題が解決した場合は、それを Oracle サポートまでお知らせください。 |
最適化を行わない JIT コンパイラが原因でコードが壊れ、ガベージ コレクションが生存しているオブジェクトを追跡できなくなっている可能性があります。起動時に -XXpreOpt
コマンドを使用し、すべてに対して最適化コンパイラを使用するように設定してください。ただし、最適化コンパイラを使用すると、JVM の起動に時間がかかる場合があります。
上記のいずれの方法でもクラッシュの問題が解決しない場合は、Oracle サポートにお問い合わせいただく必要があります。以下の情報をお知らせください。
.dump
ファイルと .mdmp
ファイルが必要。この 2 つがないと、サポート スタッフが問題を解決できません。コア ファイルである .dump
や .mdmp
のサイズが、少なくとも Java ヒープと同じくらいの大きさであることを確認してください。
Oracle サポートへの連絡方法については、「Oracle サポートへのトラブル レポートの送付」を参照してください。
![]() ![]() ![]() |