重要なアプリケーションでクラッシュが発生し、HotSpot VM内のバグによってクラッシュが発生したように見える場合は、一時的な回避策をすばやく見つけることが望ましい場合があります。このセクションの目的は、可能な回避策をいくつか示すことです。JDKの最新リリースとともに配備されたアプリケーションでクラッシュが発生した場合は、必ずOracleにクラッシュを報告するようにしてください。
警告: このセクションの回避方法によってクラッシュが正常に除去されても、その回避方法は問題の修正ではなく、一時的な解決方法でしかありません。問題が見つかった元の構成で、サポート・コールまたはバグ・レポートを提出してください。 |
システム・クラッシュの回避方法を見つけるための3つのシナリオを次に示します。
コンパイラ・スレッドでクラッシュが発生したことが致命的エラー・ログに示された場合は、コンパイラのバグが発生した可能性があります(ただし、常にそうであるとは限りません)。同様に、コンパイルされたコードでクラッシュが発生した場合は、コンパイラが不正なコードを生成した可能性があります。
HotSpot Client VM (-client
オプション)の場合は、コンパイラ・スレッドがCompilerThread0
としてエラー・ログに表示されます。HotSpot Server VMの場合は、複数のコンパイラ・スレッドがあり、それらがCompilerThread0
、CompilerThread1
、およびAdapterThread
としてエラー・ログ・ファイルに表示されます。
JDK 7u5のリリース以降、HotSpotコンパイラはデフォルトで無視されます。コマンドライン・オプションを使用して以前の動作をシミュレートすることが可能であり、これは複数のメソッドが除外されている場合に便利です。コマンドライン・オプションの詳細は、JDK 7u5での重要なバグ修正の項を参照してください。
.hotspot_compile
ファイルのかわりにJVMフラグを使用してメソッドをコンパイルから除外するには、拡張JITコンパイラ・オプションの-XX:CompileCommand
を参照してください。
例5-5は、開発中に発生し、修正されたコンパイラ・バグのエラー・ログのフラグメントを示しています。このログ・ファイルは、HotSpot Server VMが使用され、CompilerThread1
でクラッシュが発生したことを示しています。このログ・ファイルはさらに、現在のCompileTask
がjava.lang.Thread.setPriority
メソッドのコンパイルだったことを示しています。
例5-5 コンパイラ・バグのエラー・ログ
# An unexpected error has been detected by HotSpot Virtual Machine: # : # Java VM: Java HotSpot(TM) Server VM (1.5-internal-debug mixed mode) : --------------- T H R E A D --------------- Current thread (0x001e9350): JavaThread "CompilerThread1" daemon [_thread_in_vm, id=20] Stack: [0xb2500000,0xb2580000), sp=0xb257e500, free space=505k Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) V [libjvm.so+0xc3b13c] : Current CompileTask: opto: 11 java.lang.Thread.setPriority(I)V (53 bytes) --------------- P R O C E S S --------------- Java Threads: ( => current thread ) 0x00229930 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=21] =>0x001e9350 JavaThread "CompilerThread1" daemon [_thread_in_vm, id=20] :
この場合は、2つの可能な回避策があります。
強引な方法: HotSpot Client VMを指定するため、アプリケーションが-client
オプションで実行されるように構成を変更します。
丁寧な方法: java.lang.Thread.setPriority
メソッドのコンパイル中にのみバグが発生するものと想定して、このメソッドをコンパイルから除外します。
最初の(-client
オプションを使用する)方法は、一部の環境では容易に構成できる可能性があります。それ以外で、構成が複雑な場合や、VMを構成するコマンド行に容易にアクセスできない場合は、より困難になる可能性があります。一般に、HotSpot Server VMからHotSpot Client VMに切り替えることで、アプリケーションのピーク・パフォーマンスも低下します。環境によっては、実際の問題の診断と修正が完了するまで、これを容認できる場合があります。
2つ目の(メソッドをコンパイルから除外する)方法では、アプリケーションの作業ディレクトリ内に.hotspot_compilerファイルを作成する必要があります。例5-6は、このアプローチを示しています。
一般に、このファイルの形式はexclude
class methodです。ここで、classは(パッケージ名で完全修飾された)クラス、methodはメソッドの名前です。コンストラクタ・メソッドは<init>
として指定され、staticイニシャライザは<clinit>
として指定されます。
注: .hotspot_compilerファイルは、サポートされていないインタフェースです。ここでは、トラブルシューティングと一時的な回避策の特定のみを目的として記載しています。 |
アプリケーションが再起動すると、コンパイラは.hotspot_compilerファイル内の除外されたメソッドをコンパイルしようとしません。場合によっては、クラッシュの根本原因を診断してバグを修正するまで、これが一時的な救済策になる可能性があります。
HotSpot VMが例5-6に示した.hotspot_compilerファイルを正しく検出して処理したことを確認するには、実行時にログ情報を探します。注意: ファイル名の区切り文字はスラッシュではなくドットです。
ガベージ・コレクション(GC)中にクラッシュが発生した場合は、致命的エラー・ログに、VM_Operation
が進行中であることが報告されます。ここでは説明のため、ほぼ同時に処理されるGC (-XX:+UseConcMarkSweep
)は使用されないことを前提としてください。ログのTHREAD
セクションにはVM_Operation
が表示され、次のいずれかの状況を示します。
割当て用の世代コレクション
全世代のコレクション
パラレルGCの割当ての失敗
パラレルGCの永続的な割当ての失敗
パラレルGCのシステムGC
ほとんどの場合、ログで報告される現在のスレッドはVMThread
です。これは、HotSpot VMで特殊なタスクを実行するために使用される特別なスレッドです。例5-7は、シリアル・ガベージ・コレクタでのクラッシュからの致命的エラー・ログのフラグメントです。
例5-7 シリアル・ガベージ・コレクタでのクラッシュ
--------------- T H R E A D --------------- Current thread (0x002cb720): VMThread [id=3252] siginfo: ExceptionCode=0xc0000005, reading address 0x00000000 Registers: EAX=0x0000000a, EBX=0x00000001, ECX=0x00289530, EDX=0x00000000 ESP=0x02aefc2c, EBP=0x02aefc44, ESI=0x00289530, EDI=0x00289530 EIP=0x0806d17a, EFLAGS=0x00010246 Top of Stack: (sp=0x02aefc2c) 0x02aefc2c: 00289530 081641e8 00000001 0806e4b8 0x02aefc3c: 00000001 00000000 02aefc9c 0806e4c5 0x02aefc4c: 081641e8 081641c8 00000001 00289530 0x02aefc5c: 00000000 00000000 00000001 00000001 0x02aefc6c: 00000000 00000000 00000000 08072a9e 0x02aefc7c: 00000000 00000000 00000000 00035378 0x02aefc8c: 00035378 00280d88 00280d88 147fee00 0x02aefc9c: 02aefce8 0806e0f5 00000001 00289530 Instructions: (pc=0x0806d17a) 0x0806d16a: 15 08 83 3d c0 be 15 08 05 53 56 57 8b f1 75 0f 0x0806d17a: 0f be 05 00 00 00 00 83 c0 05 a3 c0 be 15 08 8b Stack: [0x02ab0000,0x02af0000), sp=0x02aefc2c, free space=255k Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) V [jvm.dll+0x6d17a] V [jvm.dll+0x6e4c5] V [jvm.dll+0x6e0f5] V [jvm.dll+0x71771] V [jvm.dll+0xfd1d3] V [jvm.dll+0x6cd99] V [jvm.dll+0x504bf] V [jvm.dll+0x6cf4b] V [jvm.dll+0x1175d5] V [jvm.dll+0x1170a0] V [jvm.dll+0x11728f] V [jvm.dll+0x116fd5] C [MSVCRT.dll+0x27fb8] C [kernel32.dll+0x1d33b] VM_Operation (0x0373f71c): generation collection for allocation, mode: safepoint, requested by thread 0x02db7108
注: ガベージ・コレクション中のクラッシュがガベージ・コレクション実装内のバグを示すとはかぎりません。コンパイラやランタイムのバグ、またはその他の問題を示す場合もあります。 |
ガベージ・コレクション中にクラッシュが繰返し発生する場合は、次の回避策を試すことができます。
GC構成を切り替えます。たとえば、シリアル・コレクタを使用している場合はスループット・コレクタを試します(またはその逆)。
HotSpot Server VMを使用している場合は、HotSpot Client VMを試します。
使用されているガベージ・コレクタがわからない場合は、Oracle SolarisおよびLinuxオペレーティング・システム上でjmap
ユーティリティを使用できます。コア・ファイルが使用可能な場合は、コア・ファイルからヒープ情報を取得するために「jmapユーティリティ」を参照してください。一般に、GC構成がコマンド行で指定されていない場合、Windowsではシリアル・コレクタが使用されます。Oracle SolarisおよびLinuxオペレーティング・システムではマシンの構成に依存します。マシンに少なくとも2 GBのメモリーと少なくとも2基のCPUが搭載されている場合は、スループット・コレクタ(パラレルGC)が使用されます。小規模なマシンでは、シリアル・コレクタがデフォルトです。シリアル・コレクタを選択するためのオプションは-XX:+UseSerialGC
で、スループット・コレクタを選択するためのオプションは-XX:+UseParallelGC
です。回避策としてスループット・コレクタからシリアル・コレクタに切り替えた場合、マルチプロセッサ・システムではパフォーマンスがある程度低下する可能性があります。根本的な問題の診断と解決が完了するまで、これを容認できる場合があります。
クラス・データ共有(CDS)は、J2SE 5.0の新機能でした。Sunの提供するインストーラを使用して32ビット・プラットフォームにJREをインストールすると、インストーラがシステムJARファイルから一連のクラスをprivate内部表現にロードして、その表現を共有アーカイブと呼ばれるファイルにダンプします。VMが起動されると、共有アーカイブはメモリーにマッピングされます。これにより、クラスのロードが減り、クラスに関連するメタデータの多くを複数のVMインスタンスで共有できます。J2SE 5.0では、HotSpot Client VMを使用する場合にのみCDSが有効になります。また、共有はシリアル・ガベージ・コレクタでのみサポートされます。
致命的エラー・ログでは、ログのヘッダーにバージョン文字列が出力されます。共有が有効な場合は、例5-8に示すように「sharing」というテキストでそれが示されます。
例5-8 クラス・データ共有のエラー・ログ
# An unexpected error has been detected by HotSpot Virtual Machine: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x08083d77, pid=3572, tid=784 # # Java VM: Java HotSpot(TM) Client VM (1.5-internal mixed mode, sharing) # Problematic frame: # V [jvm.dll+0x83d77]
CDSを無効にするには、コマンド行に-Xshare:off
オプションを指定します。共有が有効になっているときにのみクラッシュが発生する場合は、この機能にバグが発生した可能性があります。その場合は、できるだけ多くの情報を収集し、バグ・レポートを提出してください。