このコードを持っています -
try {
doSomething();
} catch (Exception e) {
e.printStackTrace();
}
これは実際にコンパイラによってどのように実装されるのでしょうか。生成されたアセンブリ コードのどこに例外のチェックが実際に組み込まれるのでしょうか。
アップデート
上記のコードがどのように翻訳されるかは分かっていますバイトコードバイトコードは try-catch を対応する try-handler ブロックに変換するだけです。これがアセンブリに変換され、JVM によって処理される方法に興味があります。
ベストアンサー1
try-catchブロックのコスト
大まかに言えば、try
ブロックは結果のアセンブリに例外チェック コードを追加しません。例外がスローされない限り、基本的に何も行いません。すべての低速な作業は、例外をスローするコードによって実行されます。
JITコンパイルされるとtry-catch
例外テーブルが追加される脇にコードから。処理された例外が発生する可能性のあるアドレス範囲を、対応する例外ハンドラーのアドレスにマップします。注記:これらはバイトコードインデックスではなく、実際のメモリアドレスです。
HotSpot で例外はどのようにスローされますか?
- 暗黙的な例外:セグメンテーション エラーに応答してシグナル ハンドラー内で検出されます
NullPointerException
。StackOverflowError
ArrayIndexOutOfBoundsException
などがClassCastException
明示的にチェックされます。対応するチェックは、配列アクセスが行われるコンパイル済みコードにインライン化されます。OutOfMemoryError
ネイティブ コードからスローされるその他のすべての例外は、スレッド状態遷移 (vm->java または native->java) が実行されるたびに明示的にチェックされます。- バイトコードによってスローされるすべてのユーザー例外
athrow
。高速パス (catch
同じフレームにハンドラーが存在する場合) では、JIT はathrow
単純なジャンプにコンパイルされます。それ以外の場合は、最適化解除が行われ、例外処理は VM ランタイム内で実行されます。
さて、「アセンブリ レベルで例外はどのようにキャッチされるのでしょうか?」
決してそうではありません。つまり
、例外は一般にアセンブリ レベルではキャッチされません。すべての重い処理 (スタック ウォーキング、ハンドラーの検索、最適化解除、モニターのロック解除など) は、VM ランタイム、つまり C コードで実行されます。