Java Platform, Standard Editionトラブルシューティング・ガイド
目次      

5.1 クラッシュの発生場所の特定

このセクションでは、エラー・ログを使用してクラッシュの原因を見つける方法を説明するいくつかの例を示し、その原因に応じて問題をトラブルシューティングするためのいくつかのヒントを提示します。

エラー・ログのヘッダーは、エラーのタイプと問題のあるフレームを示し、スレッド・スタックは現在のスレッドおよびスタック・トレースを示しています。 ヘッダー形式を参照してください。

クラッシュには次の原因が考えられます。

5.1.1 ネイティブ・コードでのクラッシュ

問題のあるフレームがネイティブ・ライブラリであることが致命的エラー・ログで示されている場合は、ネイティブ・コードまたはJava Native Interface (JNI)ライブラリ・コード内にバグが存在する可能性があります。 クラッシュが他の原因で発生した可能性ももちろんありますが、最初はライブラリとコア・ファイルまたはクラッシュ・ダンプを分析するのが適切です。 致命的なエラー・ログのヘッダーからの例5-1の抜粋を検討してください。

例5-1 致命的エラー・ログのヘッダーからの抜粋

# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  SIGSEGV (0xb) at pc=0x417789d7, pid=21139, tid=1024
#
# Java VM: Java HotSpot(TM) Server VM (6-beta2-b63 mixed mode)
# Problematic frame:
# C  [libApplication.so+0x9d7]

この場合は、ライブラリlibApplication.so内で実行されているスレッドでSIGSEGVが発生しました。

場合によっては、ネイティブ・ライブラリ内のバグがJava VMコード内のクラッシュとして表れます。 _thread_in_vm状態で(つまり、Java VMコードで実行されているとき)、JavaThreadが失敗した例5-2のクラッシュを検討してください。

例5-2 クラッシュの例

# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x08083d77, pid=3700, tid=2896
#
# Java VM: Java HotSpot(TM) Client VM (1.5-internal mixed mode)
# Problematic frame:
# V  [jvm.dll+0x83d77]

---------------  T H R E A D  ---------------

Current thread (0x00036960):  JavaThread "main" [_thread_in_vm, id=2896]
 :
Stack: [0x00040000,0x00080000),  sp=0x0007f9f8,  free space=254k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [jvm.dll+0x83d77]
C  [App.dll+0x1047]          <========= C/native frame
j  Test.foo()V+0
j  Test.main([Ljava/lang/String;)V+0
v  ~StubRoutines::call_stub
V  [jvm.dll+0x80f13]
V  [jvm.dll+0xd3842]
V  [jvm.dll+0x80de4]
V  [jvm.dll+0x87cd2]
C  [java.exe+0x14c0]
C  [java.exe+0x64cd]
C  [kernel32.dll+0x214c7]
 :

この場合、問題のあるフレームはVMフレームですが、スレッド・スタックは、App.dll内のネイティブ・ルーチンが(おそらくJNIを使って)VM内に呼び出されたことを示しています。

ネイティブ・ライブラリでのクラッシュを解決する最初のステップは、クラッシュが発生したネイティブ・ライブラリのソースを調べることです。

  • ネイティブ・ライブラリがアプリケーションによって提供されている場合は、ネイティブ・ライブラリのソース・コードを調べます。 -Xcheck:jniオプションをコマンド行に追加してアプリケーションを実行することで、JNIコードに関する多くの問題を特定できます。 -Xcheck:jniオプションを参照してください。

  • ネイティブ・ライブラリが別のベンダーから提供され、アプリケーションで使用されている場合は、このサードパーティ・アプリケーションに対するバグ・レポートを提出し、致命的エラー・ログの情報を提供します。

  • クラッシュが発生したネイティブ・ライブラリがJava Runtime Environment (JRE)の一部(awt.dllやnet.dllなど)である場合は、ライブラリまたはAPIのバグが発生した可能性があります。 その場合は、できるだけ多くのデータを収集し、ライブラリ名を示してバグまたはレポートを提出してください。 JREライブラリは、JREディストリビューションのjre/libまたはjre/binディレクトリにあります。 バグ・レポートの提出を参照してください。

ネイティブ・アプリケーション・ライブラリ内のクラッシュをトラブルシューティングするには、ネイティブ・デバッガをコア・ファイルまたはクラッシュ・ダンプ(利用可能な場合)に接続します。 ネイティブ・デバッガは、OSに応じてdbxgdb、またはwindbgです。 オペレーティング・システムのネイティブ・ツールを参照してください。

5.1.2 コンパイル済みコードでのクラッシュ

コンパイル済みコードでクラッシュが発生したことが致命的エラー・ログで示されている場合は、不正なコードを生成するコンパイラ・バグが発生した可能性があります。 問題のあるフレームのタイプがJ (コンパイル済みのJavaフレームを意味する)である場合は、コンパイル済みコードでクラッシュが発生したと認識できます。 例5-3は、このようなクラッシュを示しています。

例5-3 コンパイル済みコードでのクラッシュ

# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  SIGSEGV (0xb) at pc=0x0000002a99eb0c10, pid=6106, tid=278546
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (1.6.0-beta-b51 mixed mode)
# Problematic frame:
# J  org.foobar.Scanner.body()V
#
:
Stack: [0x0000002aea560000,0x0000002aea660000),  sp=0x0000002aea65ddf0,
  free space=1015k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
J  org.foobar.Scanner.body()V

[error occurred during error reporting, step 120, id 0xb]

ノート: 完全なスレッド・スタックは取得できません。 「error occurred during error reporting」(エラー報告中にエラーが発生しました)という出力行は、スタック・トレースを取得しようとして問題が発生したこと(スタックの破損を示している可能性がある)を意味します。

コンパイラを切り替える(たとえば、HotSpot Server VMの代わりにHotSpot Client VMを使用する、またはその逆)か、クラッシュを引き起こしたメソッドをコンパイルから除外することによって、問題を一時的に回避できる可能性があります。 この具体例ではコンパイラを切り替えられない可能性があります(これは64ビットのサーバーVMから取ったものであり、32ビットのクライアントVMへの切替えはできない可能性があるため)。

使用可能な回避方法の詳細は、「HotSpotコンパイラ・スレッドまたはコンパイル済みコードでのクラッシュの回避」を参照してください。

5.1.3 HotSpotコンパイラ・スレッドでのクラッシュ

致命的エラー・ログの出力に、現在のスレッドがCompilerThread0CompilerThread1、またはAdapterCompilerという名前のJavaThreadであることが示されている場合は、コンパイラのバグが発生した可能性があります。 この場合は、コンパイラを切り替える(たとえば、HotSpot Server VMの代わりにHotSpot Client VMを使用する、またはその逆)か、クラッシュを引き起こしたメソッドをコンパイルから除外することによって、問題を一時的に回避しなければいけないことがあります。

使用可能な回避方法の詳細は、「HotSpotコンパイラ・スレッドまたはコンパイル済みコードでのクラッシュの回避」を参照してください。

5.1.4 VMスレッドでのクラッシュ

致命的エラー・ログの出力に、現在のスレッドがVMThreadであることが示されている場合は、THREADセクションでVM_Operationを含む行を探してください。 VMThreadは、HotSpot VMの特別なスレッドです。 VM内でガベージ・コレクション(GC)などの特殊なタスクを実行します。 VM_Operationによって、操作がGCであることが示唆された場合は、ヒープの破損などの問題が発生した可能性があります。

GCの問題以外にも、ヒープ内のオブジェクト参照を不整合または不正な状態にしておく他の何か(コンパイラやランタイムのバグなど)が問題である可能性も等しくあります。 この場合は、環境に関する情報をできるだけ多く収集し、可能な回避策を試してください。 問題がGCに関連する場合は、GCの構成を変更することによって問題を一時的に回避できることがあります。

使用可能な回避方法の詳細は、「ガベージ・コレクション中のクラッシュの回避」を参照してください。

5.1.5 スタック・オーバーフローによるクラッシュ

Java言語コード内でスタック・オーバーフローが発生すると、通常は違反したスレッドがjava.lang.StackOverflowError例外をスローします。 一方、CおよびC++はスタックの終わりを越えて書込みを行い、スタック・オーバーフローを引き起こします。 これは、プロセスが終了する致命的エラーです。

HotSpot実装では、Javaメソッドがスタック・フレームをC/C++ネイティブ・コード(つまり、ユーザー・ネイティブ・コードおよび仮想マシン自体)と共有します。 Javaメソッドは、スタック空間を越えることなくネイティブ・コードを呼び出せるように、スタックの終わりに向かって一定距離のスタック空間が使用可能であるかどうかをチェックするコードを生成します。 このスタックの終わりまでの距離を「シャドウ・ページ」と呼びます。 シャドウ・ページのサイズは、プラットフォームに応じて3-20ページです。 この距離は調整可能であるため、デフォルトより長い距離を必要とするネイティブ・コードを含むアプリケーションは、シャドウ・ページのサイズを増やすことができます。 シャドウ・ページを増やすためのオプションは-XX:StackShadowPages=nです(nはプラットフォームのデフォルトのシャドウ・ページより大きくします)。

アプリケーションでセグメンテーション障害が発生したときにコア・ファイルまたは致命的エラー・ログ・ファイル(付録Aを参照)が生成されなかったか、Windows上でSTACK_OVERFLOW_ERRORが発生したか、または「An irrecoverable stack overflow has occurred」(回復不能なスタック・オーバーフローが発生しました)というメッセージが表示された場合、これはStackShadowPagesの値を超過したため、より多くの空間が必要であることを示します。

StackShadowPagesの値を増やす場合は、-Xssパラメータを使用してデフォルトのスレッド・スタック・サイズも増やす必要があることがあります。 デフォルトのスレッド・スタック・サイズを増やすと、作成できるスレッドの数が減る可能性があるため、スレッド・スタック・サイズの値は慎重に選択してください。 スレッド・スタック・サイズは、プラットフォームによって256 KBから1024 KBまで様々です。

例5-4 スタック・オーバーフロー例外

# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x10001011, pid=296, tid=2940
#
# Java VM: Java HotSpot(TM) Client VM (1.6-internal mixed mode, sharing)
# Problematic frame:
# C  [App.dll+0x1011]
#

---------------  T H R E A D  ---------------

Current thread (0x000367c0):  JavaThread "main" [_thread_in_native, id=2940]
:
Stack: [0x00040000,0x00080000),  sp=0x00041000,  free space=4k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [App.dll+0x1011]
C  [App.dll+0x1020]
C  [App.dll+0x1020]
:
C  [App.dll+0x1020]
C  [App.dll+0x1020]
...<more frames>...

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  Test.foo()V+0
j  Test.main([Ljava/lang/String;)V+0
v  ~StubRoutines::call_stub

例5-4から次の情報を解釈できます。

  • 例外はEXCEPTION_STACK_OVERFLOWです。

  • スレッドの状態は_thread_in_nativeで、スレッドがネイティブ・コードまたはJNIコードを実行していることを意味します。

  • スタック情報では、空き領域は4 KB (Windowsシステムの単一ページ)のみです。 さらに、スタック・ポインタ(sp)はスタックの終わり(0x00040000)に近い0x00041000です。

  • ネイティブ・フレームの出力は、再帰的なネイティブ関数がこの場合の問題であることを示しています。 出力の...という表記は、追加のフレームが存在するが、出力されなかったことを示します。 出力は100フレームまでに制限されています。

目次      

Copyright © 1993, 2025, Oracle and/or its affiliates. All rights reserved.