JVMはmainメソッドによってスローされた例外をどのように処理しますか?


10

私は例外を理解し、それらをスローし、それらを処理し、それらをコールスタックの下位のメソッド(つまりthrows)に伝達します。

私が理解していないのはこれです:

public static void main(String[] args) throws Exception {
    ...
}

今、私mainスローする場合Exceptionに、JVMがそれを処理すると仮定します(正しい?)。その場合、私の質問は次のとおりです。

JVMはスローされた例外をどのように処理しmainますか?それは何をするためのものか?

回答:


19

public static void mainJava のメソッドまたはmainC の関数がプログラムの実際のエントリポイントであると考えるかもしれませんが、そうではありません。すべての高水準言語(Cを含む)には、プログラムを初期化し、制御フローをエントリポイントに転送する言語ランタイムがあります。Javaの場合、初期化には以下が含まれます。

  • JVMのセットアップ
  • 必要なクラスの読み込み
  • 静的初期化ブロックを実行しています。これmainは、が呼び出される前にユーザー定義コードを実行できます。これらのブロックは例外をスローすることを想定していません。

例外処理を実装するにはさまざまな方法がありますが、この質問のために、それらはすべてブラックボックスと見なすことができます。ただし、重要なことは、言語ランタイムは常に、ユーザーコードによってキャッチされないすべての例外をキャッチする最も外側の例外ハンドラーを提供する必要があるということです。この例外ハンドラーは通常、スタックトレースを出力し、プログラムを通常の方法でシャットダウンし、エラーコードで終了します。プログラムを適切にシャットダウンするには、オブジェクトグラフの破棄、ファイナライザの呼び出し、メモリ、ファイルハンドル、ネットワーク接続などのリソースの解放が含まれます。

説明のために、次のような巨大なtry-catchですべてのコードをラップするランタイムをイメージ化できます。

try {
    loadClasses();
    runInitializers();
    main(argv);
    System.exit(0);
} catch (Throwable e) {
    e.printStackTrace();
    System.exit(-1);
}

ただし、言語が実際にこのようなコードを実行する必要はありません。同じセマンティクスthrowを、最初の適用可能な例外ハンドラーを検索する(または同等の)コードに実装できます。


9

すべてのJavaコードはスレッドのコンテキストで実行されます。リンクされたJavaDocはエラー処理と終了基準を説明していますが、その要点は次のとおりです。

  • JVMが起動し、実行環境を準備します。
  • JVMは、main()適用可能なコマンドラインパラメータを使用してメソッドを実行するスレッドを作成します。
  • JVMはデフォルトのキャッチされない例外ハンドラーを設定し、例外を標準エラーに出力して終了します。
  • JVMがスレッドを実行します。

キャッチされない例外の場合、プログラムは上記の3番目の項目に従って効果的に終了します。この動作は、Java言語仕様のセクション11.3でさらに指定されています。


追加情報

他の人は静的ブロックとそれらが以前にどのように実行されるかについて言及しましたmain()。ただし、これを正しく理解するには、もう少し説明が必要です。

クラスをロードするとき、クラスローダーは、クラスを使用する前に、すべてのstatic final状態を初期化し、すべてのstaticブロックを実行して、クラスのインスタンスを作成する必要があります(脇に、クラス定数が静的ブロックで初期化されるJavaクラス作成し、クラスのインスタンスであり、コンストラクタは定数を参照します。ただし、これはすべて、コードがクラスを参照する前に、クラスローダーロジックで発生します。さらに、クラスは、クラスを参照するスレッドにロードされます。

つまり、含むクラスがmain()別のクラス(クラス定数など)を参照している場合、そのクラスは、静的ブロックを含めるために実行前にロードする必要ありますmain()。それ以外の場合、静的ブロックは上記のように実行されます。クラスのロードに失敗すると、クラスを含むクラスmain()もロードに失敗し、プログラムが終了します。

もう1つの注意点:静的ブロックスローされる可能性があります。Errorsそのままスローされます。Exceptions禁止されています(コンパイル時エラー)。ExceptionInInitializerErrorでRuntimeExceptionsラップされます。これらは、キャッチされない例外ハンドラーごとに処理されます。クラス参照(およびロード)をtry-で慎重にラップしない限り、通常はスレッドまたはアプリケーション(メインスレッド)を強制終了しますcatch

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.