回答:
public static void main
Java のメソッドまたはmain
C の関数がプログラムの実際のエントリポイントであると考えるかもしれませんが、そうではありません。すべての高水準言語(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
ブロックを実行して、クラスのインスタンスを作成する必要があります(脇に、クラス定数が静的ブロックで初期化されるJavaクラスを作成し、クラスのインスタンスであり、コンストラクタは定数を参照します。ただし、これはすべて、コードがクラスを参照する前に、クラスローダーロジックで発生します。さらに、クラスは、クラスを参照するスレッドにロードされます。
つまり、含むクラスがmain()
別のクラス(クラス定数など)を参照している場合、そのクラスは、静的ブロックを含めるために実行前にロードする必要がありますmain()
。それ以外の場合、静的ブロックは上記のように実行されます。クラスのロードに失敗すると、クラスを含むクラスmain()
もロードに失敗し、プログラムが終了します。
もう1つの注意点:静的ブロックがスローされる可能性があります。Errors
そのままスローされます。Exceptions
禁止されています(コンパイル時エラー)。ExceptionInInitializerErrorでRuntimeExceptions
ラップされます。これらは、キャッチされない例外ハンドラーごとに処理されます。クラス参照(およびロード)をtry
-で慎重にラップしない限り、通常はスレッドまたはアプリケーション(メインスレッド)を強制終了しますcatch
。