印刷ビューの終了

HotSpot VM のトラブルシューティングガイド

印刷ビュー

ドキュメント情報

はじめに

1. 診断ツールおよびオプション

2. ツールの詳細な説明

3. メモリーリークのトラブルシューティング

4. システムクラッシュのトラブルシューティング

5. ハングアップまたはループしているプロセスのトラブルシューティング

6. シグナル処理と例外処理の統合

6.1 Solaris OS および Linux 上でのシグナル処理

6.1.1 シグナル使用の削減

6.1.2 代替シグナル

6.1.3 シグナルチェーン

6.2 Windows での例外処理

6.2.1 HotSpot 仮想マシンでのシグナル処理

6.2.2 コンソールハンドラ

7. バグレポートの提出

A. 環境変数とシステムプロパティー

B. コマンド行オプション

C. 致命的エラーログ

D. このリリースのツールのサマリー

第 6 章

シグナル処理と例外処理の統合

開発者は、Java アプリケーションをシグナルハンドラまたは例外ハンドラを使用するコードと統合しなければいけない場合があります。この章では、HotSpot 仮想マシンでのシグナルの処理方法について説明します。また、独自のシグナルハンドラをインストールする必要があるアプリケーションの記述を容易にする、シグナルチェーン機能についても説明します。シグナルチェーン機能は、Solaris OS および Linux 上で使用できます。

6.1 Solaris OS および Linux 上でのシグナル処理

HotSpot 仮想マシンは、さまざまな機能を実装して致命的エラー状態を処理するために、シグナルハンドラをインストールします。たとえば、まれに java.lang.NullPointerException がスローされた場合に明示的な NULL チェックを回避する最適化では、SIGSEGV シグナルをキャッチして処理し、NullPointerException をスローします。

一般に、シグナルやトラップが発生する状況には 2 つのカテゴリがあります。

次の表に、Solaris OS および Linux 上で現在使用されているシグナルを示します。「オプション」という記述は、「6.1.1 シグナル使用の削減」で説明するように、-Xrs オプションを指定したときにそのシグナルが不要になることを意味します。「構成可能」という記述は、「6.1.2 代替シグナル」で説明するように、代替シグナルを指定できることを意味します。シグナルチェーンの詳細は、「6.1.3 シグナルチェーン」を参照してください。

シグナル
説明
SIGSEGVSIGBUSSIGFPESIGPIPESIGILL
暗黙的な NULL チェックの実装などに使用されます。
SIGQUIT
スレッドダンプのサポート: 標準エラーストリームで Java スタックトレースをダンプします。(オプション。)
SIGTERMSIGINTSIGHUP
VM が異常終了したときにシャットダウンフックメカニズム (java.lang.Runtime.addShutdownHook) をサポートするために使用されます。(オプション。)
SIGUSR1
java.lang.Thread.interrupt メソッドの実装で使用されます。(構成可能。) Solaris 10 OS 以降では使用されません。Linux では予約されています。
SIGUSR2
内部で使用されます。(構成可能。) Solaris 10 OS 以降では使用されません。
SIGABRT
HotSpot VM はこのシグナルを処理しません。代わりに、致命的エラー処理のあとで abort 関数を呼び出します。アプリケーションでこのシグナルを使用する場合は、期待されるセマンティクスを保持するため、プロセスを終了するようにしてください。

6.1.1 シグナル使用の削減

-Xrs オプションは、シグナルの使用を減らすように HotSpot VM に指示します。このオプションを使用すると、使用されるシグナルの数が減りますが、VM は SIGSEGV などの基本的なシグナルのために独自のシグナルハンドラをインストールします。-Xrs を指定すると、上の表で「オプション」と記述されたシグナルは使用されません。このオプションを指定すると、プロセスが SIGQUITSIGTERMSIGINT、または SIGHUP を受信した場合にシャットダウンフックメカニズムが実行されなくなります。VM が正常終了した (最後の非デーモンスレッドが完了するか、System.exit メソッドが使用された) 場合は、シャットダウンフックが予想どおり実行されます。

6.1.2 代替シグナル

Solaris 8 および 9 OS では、-XX:+UseAltSigs オプションを使用して、SIGUSR1 および SIGUSR2 の代替シグナルを使用するように HotSpot VM に指示できます。Solaris 10 OS 以降では、オペレーティングシステムが (SIGJVM1 および SIGJVM2 という名前の) 2 つの追加シグナルを予約しているため、このオプションは無視されます。

Linux では、SIGUSR1 のハンドラをオーバーライドすることはできません。SIGUSR2 は、suspend と resume を実装するために使用されます。ただし、SIGUSR2 の代わりに代替シグナルを使用するように指定することも可能です。これを行うには、_JAVA_SR_SIGNUM 環境変数を指定します。この環境変数を設定する場合は、SIGSEGV および SIGBUS の最大より大きい値に設定する必要があります。

6.1.3 シグナルチェーン

ネイティブコードを含むアプリケーションに独自のシグナルハンドラが必要な場合は、シグナルチェーン機能とともにアプリケーションを使用しなければいけないことがあります。シグナルチェーン機能は、次の機能を提供します。

SIGUSR1 はチェーンできません。Solaris OS 上でアプリケーションがこのシグナルをチェーンしようとすると、HotSpot VM は次の致命的エラーで終了します。

Signal chaining detected for VM interrupt signal, try -XX:+UseAltSigs

さらに、SIGQUITSIGTERMSIGINT、および SIGHUP シグナルもチェーンできません。アプリケーションでこれらのシグナルを処理する必要がある場合は、-Xrs オプションの使用を検討してください。

Solaris OS では、SIGUSR2 シグナルをチェーンできますが、Java 以外かつ VM 以外のスレッド専用です。つまり、VM に接続していないアプリケーションで作成されたネイティブスレッドでのみ使用できます。

6.2 Windows での例外処理

Windows では、例外はプログラムの実行中に発生するイベントです。例外には、ハードウェア例外とソフトウェア例外の 2 種類があります。ハードウェア例外は、Solaris OS および Linux 上の SIGSEGVSIGKILL などのシグナルに相当します。ソフトウェア例外は、アプリケーションまたはオペレーティングシステムが RaiseException() API を使用して明示的に発行します。

Windows では、ハードウェア例外とソフトウェア例外の両方を処理するメカニズムを構造化例外処理 (SEH) と呼びます。これは、C++ や Java の例外処理メカニズムに似たスタックフレームベースの例外処理です。C++ では、次の例のように __try および __except キーワードを使用して、例外が発生する可能性があるコードのセクションを保護します。

__try {
     // guarded body of code
 } __except (filter-expression) {
     // exception-handler block
 }

__except ブロックは、例外コード (GetExceptionCode() API から返される整数コード)、例外情報 (GetExceptionInformation() API)、またはその両方を使用するフィルタ式によってフィルタ処理されます。

このフィルタ式は、次のいずれかの値として評価されるはずです。

終了ハンドラを構築するには、以下に示すように __try および __finally キーワードを使用します。

__try { 
    // guarded body of code  
} __finally { 
    // __finally block  
}

(例外のあと、または例外なしで) __try ブロックに制御が残ったときは、__finally ブロックが実行されます。__finally ブロックの内部で AbnormalTermination() API を呼び出すと、例外のあとで制御が継続したかどうかをテストできます。

Windows プログラムは、最上位の未処理例外フィルタ関数をインストールして、__try/__except ブロックで処理されない例外をキャッチすることもできます。この関数は、SetUnhandledExceptionFilter() API を使用してプロセス単位でインストールされます。ある例外のハンドラが存在しない場合は、UnhandledExceptionFilter() が呼び出され、これが最上位の未処理例外フィルタ関数を (あれば) 呼び出して、その例外をキャッチします。この関数によって、未処理例外をユーザーに通知するメッセージボックスも表示されます。

Windows の例外は、現在の実行ストリームに起因する Unix の同期シグナルに相当します。Windows では、コンソールイベント (たとえば、ユーザーがコンソールで Ctrl + C を押した場合) などの非同期イベントは、SetConsoleCtlHandler() API を使用して登録されたコンソール制御ハンドラによって処理されます。

Windows 上でアプリケーションが signal() API を使用すると、C 実行時ライブラリ (CRT) は Windows の例外とコンソールイベントの両方を適切なシグナルまたは C 実行時エラーにマップします。たとえば、CRT は Ctrl + C を SIGINT に、ほかのすべてのコンソールイベントを SIGBREAK にマップします。同様に、SIGSEGV ハンドラを登録すると、C 実行時ライブラリは対応する例外をシグナルに変換します。CRT ライブラリの起動コードは、main() 関数の周囲に __try/__except ブロックを実装しています。CRT の例外フィルタ関数 (名前は _XcptFilter) は、Win32 例外をシグナルにマップし、シグナルを適切なハンドラにディスパッチします。シグナルのハンドラを SIG_DFL (デフォルトの処理) に設定すると、_XcptFilterUnhandledExceptionFilter を呼び出します。

Windows XP または Windows 2003 では、ベクトル化例外処理メカニズムを使用することもできます。ベクトル化ハンドラは、フレームベースのハンドラではありません。プログラムは、AddVectoredExceptionHandler API を使用して 0 個以上のベクトル化例外ハンドラを登録できます。ベクトル化ハンドラは、構造化例外ハンドラ (あれば) の前に呼び出され、例外の発生場所に関係なく呼び出されます。

ベクトル化例外ハンドラは、次のいずれかの値を返します。

Windows の例外処理の詳細は、Microsoft の Web サイト (http://www.microsoft.com) を参照してください。

6.2.1 HotSpot 仮想マシンでのシグナル処理

HotSpot VM は、VM の初期化中に SetUnhandledExceptionFilter API (64 ビットの場合は AddVectoredExceptionHandler API) を使用して最上位の例外ハンドラをインストールします。

また、作成される各スレッドのスレッド (内部) 起動関数呼び出しの周囲に、C++ の __try /__except ブロックを使用して win32 SEH をインストールします。

最後に、JNI 関数の周囲に例外ハンドラをインストールします。

アプリケーションで JNI コード内の構造化例外を処理する必要がある場合は、C++ の __try /__except 文を使用できます。ただし、JNI コード内でベクトル化例外ハンドラを使用する必要がある場合、そのハンドラは VM の例外ハンドラに進むために EXCEPTION_CONTINUE_SEARCH を返す必要があります。

一般に、例外が発生する状況には 2 つのカテゴリがあります。

6.2.2 コンソールハンドラ

HotSpot 仮想マシンは、次の表に示すコンソールイベントを登録します。

コンソールイベント
シグナル
使用法
CTRL_C_EVENT
SIGINT
プロセスを終了します。(オプション)
CTRL_CLOSE_EVENT CTRL_LOGOFF_EVENT CTRL_SHUTDOWN_EVENT
SIGTERM
VM が異常終了したときにシャットダウンフックメカニズムによって使用されます。(オプション)
CTRL_BREAK_EVENT
SIGBREAK
スレッドダンプのサポート。標準エラーストリームで Java スタックトレースをダンプします。(オプション)

アプリケーションが独自のコンソールハンドラを登録する必要がある場合は、-Xrs オプションを使用できます。このオプションを使用すると、(上記のイベントのマッピングによる) SIGTERM に対してシャットダウンフックが実行されず、(上記の Ctrl + Break イベントのマッピングによる) SIGBREAK に対してスレッドダンプのサポートを利用できなくなります。