診断ガイド

     前  次    目次     
コンテンツの開始位置

システムのクラッシュ

Java アプリケーションは、さまざまな原因で動作を停止する場合があります。当然のことながら、最も一般的な原因は、アプリケーションの動作が完了したこと、または正常に中断したことです。その他の原因としては、Java アプリケーション エラー、未処理の例外または OutOfMemoryError などの回復できない Java エラーが考えられます。場合によっては、JVM 自体で正常に回復できなかった問題が起きたことを意味する JVM クラッシュが発生する可能性があります。クラッシュが発生した場合に Oracle JRockit JVM が出力するダンプ情報から、JVM クラッシュを特定することができます。

このドキュメントでは、JVM のクラッシュを診断し、解決する方法を説明します。内容は以下のとおりです。

 


Oracle サポートへの通知

Oracle とのサポート契約がない場合でも、JRockit JVM で問題が発生した場合は、Oracle サポートまでご連絡ください。連絡をいただくと、Oracle では次回のリリースでその問題が修正されていることを確認できます。Oracle サポートへの連絡方法については、「Oracle サポートへのトラブル レポートの送付」を参照してください。

 


クラッシュの分類

JVM クラッシュの診断と解決の第一段階は、クラッシュの分類です。たとえば、クラッシュが発生した場所および原因を特定します。

クラッシュ ファイルの使用

JRockit JVM はクラッシュすると、クラッシュした時点でのコンピュータと JVM プロセスの状態のスナップショットを作成し、その情報を次のいずれかの「クラッシュ ファイル」に書き込みます。

バイナリ クラッシュ ファイル (Core ファイルと mdmp ファイル) は、Oracle サポートが JRockit JVM の問題を解決するのに非常に役に立ちます。ただし、Oracle システムとサービス契約を結んでいないと、これらのファイルはあまり役に立ちません。

クラッシュの種類の特定

テキスト dump ファイルを取得し、クラッシュの種類を示す情報について確認することで、クラッシュが発生した場所と原因を特定できる場合があります。オペレーティング システムのセットアップのチェックに加えて、バイナリ dump ファイルのサイズをチェックすることが、役に立つ場合があります。表 30-1 に、発見可能な兆候と、それらの兆候に対応する、予想されるクラッシュの種類を示します。

表 30-1 クラッシュの診断とクラッシュの種類
兆候
予想されるクラッシュの種類
dump ファイルが、JVM プロセスで仮想メモリが不足していることを示しています。詳細については、「クラッシュ ファイルの概要」を参照してください。
core ファイルまたは mdmp ファイルのサイズが、その OS におけるプロセスの仮想メモリ サイズの最大値に近い値になっています。詳細については、「クラッシュ ファイルの概要」を参照してください。
dump ファイルが、スタック オーバーフロー エラーが発生したことを示しています。詳細については、「クラッシュ ファイルの概要」を参照してください。
Linux 固有の問題
dump ファイルが、LD_ASSUME_KERNEL が設定されていることを示しています。詳細については、「クラッシュ ファイルの概要」を参照してください。
Linux 固有の問題
非標準またはサポートされない Linux コンフィグレーションを使用しています。
上記のいずれも当てはまらないか、または問題が解決されません。

 


仮想メモリ不足のクラッシュ

JVM は、Java ヒープ、Java メソッド、スレッド スタックおよび JVM 内部データ構造など、さまざまな目的で仮想メモリを確保します。さらに、ネイティブ (JNI) コードでも、メモリを割り当てることができます。プロセス サイズは、JVM によって確保されたすべてのメモリから構成され、オペレーティング システムの制限に応じて制限されます。JVM プロセスの仮想メモリの割り当てがこれらの制限を超えると、JVM で仮想メモリが不足し、クラッシュが発生する可能性があります。この節では、以下のトピックを取り上げます。

仮想メモリ不足エラーの確認

仮想メモリ不足エラーのデバッグを開始する前に、まず、エラーが本当に JVM プロセスでの仮想メモリ不足によるものであるのかを確認する必要があります。この節では、以下の情報について説明します。

仮想メモリの最大値

表 30-2 にビットの各種オペレーティング システムで使用可能な仮想メモリの最大値を示します。64 ビットのプラットフォームでは、仮想メモリは実質的に無制限です。

表 30-2 IA32 アーキテクチャで使用可能な仮想メモリの概算の最大値
OS
最大プロセス仮想メモリ
Windows
2GB
Windows /3GB 起動オプション
3GB
Linux (標準)
3GB

テキスト dump ファイルのチェック

テキスト dump ファイルは、JVM によって作成された場合、メモリの割り当てに失敗したことを示す可能性があります。詳細については、「クラッシュ ファイルの概要」を参照してください。これは、JVM プロセスで仮想メモリが不足していることを顕著に示しています。

バイナリ mdmp または core ファイルのチェック

JRockit JVM がクラッシュすると、バイナリ クラッシュ ファイルが生成されます。デフォルトでは、このファイルには JVM プロセス全体のコピーが含まれます。このファイルのサイズをチェックして、JVM プロセスで本当に仮想メモリが不足しているかどうかを判断してください。

  1. バイナリ クラッシュ ファイルのサイズが、コマンド ライン オプションの -XXdumpSize またはオペレーティング システム コマンドの ulimit (Linux および Solaris のみ) を使用して制限されていないことを確認します。コマンド ulimit -a を使用して、Linux および Solaris でクラッシュ ファイルのサイズが無制限であることを確認してください。バイナリ クラッシュ ファイルのサイズが制限されていると、このコマンドを使用して JVM プロセスで仮想メモリが不足しているかどうかを確認できません。
  2. mdmp または core ファイルのサイズをヒープと比較し、ヒープのサイズよりも大きいことを確認します。これは、バイナリ クラッシュ ファイルが、ディスク領域の制限などによって切り捨てられていないことを確認するためのサニティ チェックです。
  3. mdmp または core ファイルのサイズが特定の OS によって許可されているプロセスの最大サイズに近づいているかどうかを判断します。

仮想メモリ不足エラーのトラブルシューティング

JVM プロセスで仮想メモリが不足していることを確認したら、問題を解決するためのトラブルシューティングを開始できます。この節では、以下のトピックを取り上げます。

JRockit JVM の最新のバージョンへのアップグレード

最新の JRockit JVM リリースを実行していることを確認してください。JVM のメモリ使用の問題を解決したり、使用量を減らしたりする修正プログラムが数多く作成されています。主要な JDK に最新バージョンの JVM を使用すれば、メモリ効率が最も高くなります。

Java ヒープ サイズの削減

Java ヒープは、JVM で使用されるメモリの合計の一部に過ぎません。Java ヒープが大き過ぎると、Java メソッドがコンパイルおよび最適化される際、またはネイティブ ライブラリが読み込まれる際に、JVM が起動できないか、または仮想メモリが不足する場合があります。このような状況が発生する場合、最大ヒープ サイズの設定を下げてみる必要があります。

Windows/3GB 起動オプションの使用

Windows 2000 Advances Server および Datacenter、Windows 2003 および Windows XP では、BOOT.INI で /3GB オプションを指定してオペレーティング システムを起動するオプションがあります。このオプションを指定すると、最大仮想メモリ プロセス サイズは 2GB から 3GB に変更されます。

JNI コードのメモリ リークのチェック

使用している JNI コードにメモリ リークがないかをチェックします。JNI コードが適切に記述または使用されていないと、メモリ リークが発生する場合があります。これにより、プラットフォームでの仮想メモリの最大サイズに達するまで、Java プロセスが増大します。

仮想メモリの使用状況の記録

仮想メモリの使用状況を記録すると、メモリ使用量の増加が確認できるため、仮想メモリ不足の問題を識別し、診断するのに役立ちます。この節では、以下について、仮想メモリの使用状況の統計を集める方法を説明します。

Windows

Windows ツールの perfmon を使用して、PrivateBytes プロセス カウンタを記録します。JVM プロセスで予約された仮想メモリの量に関する情報を収集してください。次の手順に従います。

  1. [管理ツール] の [パフォーマンス モニタ] を開きます。
  2. [+] をクリックして [カウンタの追加] ダイアログ ボックスを開きます。
  3. [パフォーマンス オブジェクト] ドロップダウン リストを開いて [Process] をクリックします。
  4. [Process] のリストから [Private Bytes] のカウンタを選択します。
  5. 監視するプロセスを選択して [追加] をクリックします。
Linux

仮想メモリの使用状況を、一定の間隔で記録するためのスクリプトを作成します。以下に例を示します。

top -b -n 10 > virtualmemory.log

このスクリプトは 10 秒おきに「top」を実行し、そのデータを virtualmemory.log ファイルに記録します。実行中の全プロセスの仮想メモリ使用量が、このファイルの VIRT 列に記録されます。現在の状態だけを確認するには、top と入力して〔Shift〕+〔M〕を押し、出力をメモリ使用量でソートします。これで、通常は JVM プロセスが出力の一番上に並びます。

Virtualmemory.log のような記録を作成すると、JRockit JVM プロセスによってメモリ使用量が実際に増加していることを確認でき、それを BEA サポートに証拠として提示できるので便利です。

問題が解決できない場合の Oracle サポートへの連絡

以上の方法で問題が解決しない場合は、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]

スタック オーバーフロー エラーに対する JRockit JVM の抵抗力を強くする

-Xcheckedstacks を使用すると、JRockit JVM のスタック オーバーフロー エラーに対する抵抗力を強化できます。これによって、通常は JVM がダンプしなくなり、java.lang.StackOverflowError を送出しなくなります。このオプションを指定すると、JVM がスタック上のページにアクセスするので、パフォーマンスがやや低下します。

 


サポートされない Linux コンフィグレーションのクラッシュ

JRockit JVM を Linux で実行中にアプリケーションがクラッシュした場合は、linux コンフィグレーションがサポート対象でないことが原因である可能性があるので、スタック トレースにクラッシュの理由が示されていても、サポート対象の Linux コンフィグレーションで実行しているかを確認する必要があります。以下を確認してください。

OS のバージョンがサポート対象かどうかの確認

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 2.3.4 2.25 i386

サポート対象でない glibc を使用しています。glibc のバージョンを、「i386」と表示されないものにアップグレードする必要があります。サポート対象のシステムからの出力の例を以下に示します。

glibc 2.3.4 2.25 i686

スレッド ライブラリの確認

コア ファイルが gdb にある場合は、次のコマンドを実行することによって、どのスレッド ライブラリを使用しているかに関してヒントを得ることができます。

info shared

ロードされた libpthread<x>.so のパスを確認してください。

/lib/ 下にある場合は、rpm コマンドの結果を調べる必要があります。この出力に「i386」のように書かれている場合は、サポート対象でない glibc を使用しているので、glibc のバージョンをアップグレードする必要があります。

 


JVM クラッシュ

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 ファイルを作成、使用する

opt ファイルは 1 文字のコードであるディレクティブが記述されたテキスト ファイルです。ディレクティブはオプティマイザに特定のメソッドを最適化しないという指示や、必ず最適化するという指示を出します。Opt ファイルを作成したら、-djrockit.optfile=<filename> プロパティ (<filename> は opt ファイル) を使用して、opt ファイルの名前と場所を指定することができます。

コード リスト 30-1 に、このファイルの内容を示します。

コード リスト 30-1 opt ファイルの例
  - 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 ファイルの設定を確認する

opt ファイルが期待どおりに機能していることを確認するには、-Xverbose:opt を使用して出力をチェックします。除外したメソッドは表示されないはずです。

Ctrl-Break ハンドラを使用して opt ファイルを設定する

Ctrl-Break ハンドラを使って opt ファイルを設定することもできます。このハンドラの名前は run_optfile です。正式な opt ファイルを <filename> 引数として受け取ります。以下に例を示します。

run_optfile optfile=<filename>

ctrl-break は押した場合は、“-”にマッチングするすべてのメソッドは、optfile でディレクティブする最適化されません。

ディレクティブの規則

opt ファイルの作成には、以下の規則が適用されます。

外部のインスツルメンテーション ツールが原因かどうかの検討

クラッシュの原因がコンパイルに失敗したメソッドではないとわかり、外部のインスツルメンテーション ツール (JProbe や OptimizeIt など) を使用している場合は、このツールが問題の原因でないか調査するとよい場合があります。これらのツールはバイトコードを書き換えることがあり、予期しない動作の原因となる可能性があります。場合によってはツールに直接の問題があることも考えられますが、JRockit JVM が抱える問題によってツールがクラッシュを起こしているケースもあります。クラッシュの原因からツールを除外するには、ツールを無効にしてアプリケーションを再実行します。それでもクラッシュが起きる場合は、インスツルメンテーション ツールが原因ではありません。アプリケーションが正常に実行される場合は、別のツールを使用するか、ツールを使わずに実行する必要があります。

サポートへの問い合わせ

Opt ファイルの回避策でも問題が軽減しない、または問題のあるメソッドを最適化せずにアプリケーションを正常に実行することができない場合は、Oracle サポートにお問い合わせいただく必要があります。Oracle に問題を報告する方法、およびその際に提出する情報については、「Oracle サポートへのトラブル レポートの送付」を参照してください。

コード生成のクラッシュの場合、Oracle サポートに以下のデータを提示していただく必要があります。

ガベージ コレクションのクラッシュ

この節では、ガベージ コレクションのクラッシュを特定およびトラブルシューティングする方法について説明します。内容は以下のとおりです。

ガベージ コレクションのクラッシュの特定

テキスト dump ファイルのスタック トレースを調べることで、ガベージ コレクションのクラッシュを特定できます。スタック トレースにガベージ コレクション関数がある場合、またはクラッシュの原因となったスレットがガベージ コレクション スレッドの 1 つである場合、クラッシュがガベージ コレクション中に発生した可能性が最も高くなります。スタック トレース内のガベージ コレクション関数は、mmgcyc、および oc などのプレフィックスで識別されます。

最新バージョンの JRockit JVM へのアップグレードの検討

ガベージ コレクションのクラッシュが発生した場合、最も簡単で最も推奨される解決方法は、JRockit JVM を最新のバージョンにアップグレードすることです。問題を細かく診断すると、非常に複雑で大変な時間がかかることがあります。最新バージョンの JVM ではその問題が修正されている場合があるため、アップグレードすると問題を回避できる可能性があります。

回避策の試行

JVM を最新のバージョンにアップグレードしない (できない) 場合、または既に最新バージョンの JVM を使用している場合は、以下のいずれかの方法でガベージ コレクションのクラッシュを回避できないか試してください。

ガベージ コレクタを変更する

使用中のガベージ コレクタにバグがあり、別のガベージ コレクタに変えることでバグを回避できる場合があります。ただし、コレクタを変更すると、Oracle JRockit JVM から同じパフォーマンス プロファイルを得られなくなります。

確定的ガベージ コレクションを使用している場合、別のガベージ コレクタに変えることはできません。確定的ガベージ コレクションの機能を保持する必要があります。ガベージ コレクタを変える代わりに、Oracle サポートに問い合わせてください。

圧縮を無効にする

ヒープを圧縮のバグにより、ガベージ コレクションのクラッシュの原因となる問題が発生する場合があります。圧縮を無効にするには、起動時に -XXnoCompaction を設定します。ただし、このオプションを使用するとヒープが断片化するおそれがあるため、トラブルシューティングを行う場合にのみ使用してください。ヒープが断片化されすぎると、メモリ不足エラーが発生するおそれがあります。

インライン化を無効にする

誤ったインライン化によってコードが壊れ、それが原因でガベージ コレクタが生存しているオブジェクトを追跡できなくなる場合があります。インライン化を無効にするには、コマンドライン オプションを組み合わせて -XXnoJITInline -XnoOpt のように指定します。このようにオプションを 2 つ使う必要があるのは、-XXnoJITInline はメソッドが最初にコンパイルされるときのみインライン化を無効にするからです。一緒に -XnoOpt を設定しなければ、コードが最適化されるときにメソッドがインライン化される可能性があります。

注意 : -XnoOpt (-XXnoJITInline なし) で問題が解決した場合は、コードの最適化が問題の原因かもしれません。逆に、-XXnoJITInline (-xnoopt なし) で問題が解決した場合は、それを Oracle サポートまでお知らせください。
最適化コンパイラを使用する

最適化を行わない JIT コンパイラが原因でコードが壊れ、ガベージ コレクションが生存しているオブジェクトを追跡できなくなっている可能性があります。起動時に -XXpreOpt コマンドを使用し、すべてに対して最適化コンパイラを使用するように設定してください。ただし、最適化コンパイラを使用すると、JVM の起動に時間がかかる場合があります。

問題が解決できない場合の Oracle サポートへの連絡

上記のいずれの方法でもクラッシュの問題が解決しない場合は、Oracle サポートにお問い合わせいただく必要があります。以下の情報をお知らせください。

Oracle サポートへの連絡方法については、「Oracle サポートへのトラブル レポートの送付」を参照してください。


  ページの先頭       前  次