私は例外を理解し、それらをスローし、それらを処理し、それらをコールスタックの下位のメソッド(つまり、throws
)に伝達します。
私が理解していないのはこれです:
public static void main(String[] args) throws Exception {
...
}
さて、私はassumemain
がException
をスローした場合、JVMがそれを処理します(正しい?)。その場合、私の質問は次のとおりです。
JVMはmain
によってスローされた例外をどのように処理しますか?それは何をするためのものか?
public static void main
Java=またはCのmain
関数は、プログラムの実際のエントリポイントですが、そうではありません。すべての高水準言語(Cを含む)は、プログラムを初期化し、制御フローをエントリポイントに転送する言語ランタイムJavaの場合、初期化には次のものが含まれます。
main
が呼び出される前にユーザー定義コードを実行できます。これらのブロックは、例外をスローすることになっています。例外処理を実装するにはさまざまな方法がありますが、この質問のために、それらはすべてブラックボックスと見なすことができます。ただし、重要なことは、言語ランタイムは常に、ユーザーコードによってキャッチされないすべての例外をキャッチする最も外側の例外ハンドラーを提供する必要があることです。この例外ハンドラーは通常、スタックトレースを出力し、プログラムを通常の方法でシャットダウンし、エラーコードで終了します。プログラムを適切にシャットダウンするには、オブジェクトグラフの破棄、ファイナライザの呼び出し、メモリ、ファイルハンドル、ネットワーク接続などのリソースの解放が含まれます。
説明のために、次のような巨大なtry-catchですべてのコードをラップするランタイムをイメージ化できます。
try {
loadClasses();
runInitializers();
main(argv);
System.exit(0);
} catch (Throwable e) {
e.printStackTrace();
System.exit(-1);
}
ただし、言語がこのようなコードを実際に実行する必要はありません。同じセマンティクスを、最初の適用可能な例外ハンドラーを検索するthrow
(または同等のもの)のコードに実装できます。
すべてJavaコードは スレッドのコンテキストで実行されます 。リンクされたJavaDocはエラー処理と終了基準を説明しますが、ここにその要点があります:
main()
メソッドを実行するスレッドを作成します。キャッチされない例外の場合、プログラムは上記の3番目の項目に従って効果的に終了します。この動作は、 Java言語仕様、セクション11.3 でさらに指定されています。
他の人は静的ブロックとそれらがmain()
の前にどのように実行されるかについて言及しました。ただし、これを正しく理解するには、もう少し説明が必要です。
クラスをロードするとき、クラスローダーはすべての_static final
_状態を初期化し、すべてのstatic
ブロックを実行する必要がありますbeforeクラスのインスタンス化インスタンスを含めるためにクラスを使用できます( :Javaクラス定数が静的ブロックで初期化されるクラスafterクラスを作成し、コンストラクターが定数を参照します。ブーム!)を作成します。ただし、これはすべてクラスローダーロジックで発生しますコードがクラスを参照する前にさらに、クラスは、クラスを参照するスレッドにロードされます。
これが意味することは、main()
を含むクラスが別のクラス(例:クラス定数)を参照する場合、そのクラスmustは、main()
が実行されてその静的ブロックを含む前にロードされます。 。それ以外の場合、静的ブロックは上記のように実行されます。クラスのロードに失敗した場合、main()
を含むクラスもロードに失敗し、プログラムが終了します。
別の参考情報:静的ブロックcan throw。 Errors
はそのままスローされます。 Exceptions
は禁止されています(コンパイル時エラー)。 RuntimeExceptions
は ExceptionInInitializerError で囲まれています。これらは、キャッチされない例外ハンドラーごとに処理されます。クラス参照(およびロード)をtry
-catch
で慎重にラップしない限り、通常はスレッドまたはアプリケーション(メインスレッド)を強制終了します。