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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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から次の情報を解釈できます。

  • 例外はEXCEPTION_STACK_OVERFLOWです。

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

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

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

目次      

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