8

私の理解でthrowは、これは基本的なjvmコマンドです。これが呼び出されると、JVMは「現在のコールスタックがそれをキャッチできるかどうかをチェックします」。それができない場合、javaは、returnが呼び出されたかのように、呼び出しスタックを単純にポップします。次に、jvmは「現在のコールスタックがそれをキャッチできるかどうかをチェックします」などと再帰的に続きます。

私の質問:JVMがコールスタックのどこで特定の例外をキャッチできるかをアルゴリズムで知るにはどうすればよいですか?例外をコードブロックにマッピングする各コールスタックエントリにメタデータが保存されていますか?どういうわけかこれを追跡する静的データ構造がヒープにありますか?どこかにそれを追跡するデータがなければならないからです。

4

2 に答える 2

9

JVM仕様には、これに関する詳細があります。

特に、セクション4.7.3では、例外テーブルについて詳しく説明しています。例外テーブルは、どの命令間でどの例外がキャッチされるかを示す一連のエントリです。セクション3.12は、この具体的な例を示しています。

もちろん、このメタデータがJITのネイティブコードにどのようにマッピングされるかは別の問題であり、実装固有です。たとえば、ネイティブJITtedコードの各命令位置から元のバイトコード位置に戻るマッピングが存在する可能性があります。その時点で、例外テーブルを参照して適切なハンドラーを見つけることができます。

于 2012-10-31T23:20:12.160 に答える
1

一般的に言えば、例外がスローされると、JVMは「呼び出しスタック」を抽出します。これにより、コールスタックの各レベルで実行されていたバイトコードまたはマシン命令が、その場所に関連付けられたクラスとメソッドとともに識別されます。

次に、スタック内の各メソッド(例外が発生したメソッドから開始して逆方向に動作)について、JVMはメソッドのテーブルマッピングtry / catch範囲をバイトコード/マシン命令範囲に(内部クラスオブジェクトで)調べます。

catchメソッドのテーブルで「一致」が見つかり、スローされる例外のタイプが、見つかった範囲で監視されているクラスである場合、例外をある種のパラメーターに設定した後、制御がエントリポイントに移されます。catch句がそれを参照できるように場所。

テーブルに「一致」が見つからない場合、呼び出しスタックは効果的に「ポップ」され、スタックの一番上に次の前のメソッドが配置され、上記のtry/catchの前のメソッドのテーブルで「一致」が検索されます。範囲が繰り返されます。

もちろん、これは単純化しすぎです。範囲の処理には多くの追加ロジックが含まれfinallyます。たとえば、いくつかの「エッジ」ケースがあります。

于 2014-07-29T02:56:26.503 に答える