web-dev-qa-db-ja.com

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

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

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

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

さて、私はassumemainExceptionをスローした場合、JVMがそれを処理します(正しい?)。その場合、私の質問は次のとおりです。

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

10
Aviv Cohn

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

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

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

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

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

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

19
amon

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

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

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


追加情報

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

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

これが意味することは、main()を含むクラスが別のクラス(例:クラス定数)を参照する場合、そのクラスmustは、main()が実行されてその静的ブロックを含む前にロードされます。 。それ以外の場合、静的ブロックは上記のように実行されます。クラスのロードに失敗した場合、main()を含むクラスもロードに失敗し、プログラムが終了します。

別の参考情報:静的ブロックcan throw。 Errorsはそのままスローされます。 Exceptionsは禁止されています(コンパイル時エラー)。 RuntimeExceptionsExceptionInInitializerError で囲まれています。これらは、キャッチされない例外ハンドラーごとに処理されます。クラス参照(およびロード)をtry-catchで慎重にラップしない限り、通常はスレッドまたはアプリケーション(メインスレッド)を強制終了します。

9
user22815