2013-11-04 3 views
6

try {} catch {}ブロックとスタックのトレースがどのように機能するのかを知りたいですか?`try/catch`はどのように詳細に動作するのですか

私はthis great article about exception handling anti-patternsを読み、次の段落を発見された:

catch (NoSuchMethodException e) { 
    throw new MyServiceException("Blah: " + 
     e.getMessage()); 
} 

は、これは元の例外のスタックトレースを破壊し、常に間違っています。

はその後、私はどのように try/catch作品ではない が本当に知っていることに気づきました。私の理解は次のとおりです。例を考えてみましょう:

void top() { 
    try { 
     f(); 
    } catch (MyException ex) { 
     handleIt(); 
    } finally { 
     cleanup(); 
    } 
} 

void f() { 
    g(); 
} 

void g() { 
    throw new MyException(); 
} 

私はtop()を呼び出すと、呼び出しチェーンtop -> f -> g は(topf機能のための)コールスタック上の2つのstack framesを残します。 gで例外が発生すると、 プログラムは例外を処理するブロックtry/catchが見つかるまで実行スタックをバブルアップします。一方、スタックフレームを解放し、スタックトレース情報をcatchに渡すことができるいくつかの "マジック"オブジェクトに添付し、スタックトレースを印刷することができます。

呼び出された関数がtry/catchブロックで「囲まれている」ことをどのように知っていますか?この情報はスタックフレームにバインドされていますか?同様に、エラー処理ブロックへのポインタ(一致するcatchブロックを選択するスイッチ)と、finallyブロックへのポインタ?なぜ上記の例ではe.getMessage()が破壊的なのでしょうか(コメント参照)?

注、私はてみ使用する方法/キャッチし、例外を知っ、私はそれがに動作します方法を知りたいです。

+0

あなたは正しいです、私は 'スロー'に気づかなかった:)しかし残りの質問はまだ有効です –

答えて

6

try/catchブロックで 『囲まれた「どのようにそれが呼び出された関数がされていることを知っていませんか』?「

各メソッドのコードは、その方法の全てのtry-catchのブロックを記述するException Tableを含有する。

手順(関数、メソッド)が呼び出されると、現在のスタックフレームは、呼び出しのアドレスが付加されています

throwステートメントが実行されると、JVM examines each stack frameはそのフレームが例外を処理できるかどうかを調べることができます。メソッドには呼び出し命令を含むtry-catchブロックが含まれ、ブロックの例外の型はthのスーパータイプ(または同じ)ですルーン例外。そのようなフレームが見つかると、フレームはtry-catchブロックから指示された命令からその実行を復元する。

3

例外がスローされると、完全な呼び出しスタック情報がいくつかのマジックオブジェクトではなく、作成された例外オブジェクトに付加されます。これは、例外が "バブルアップ"している間は発生しません。この例外は、作成されたときに発生し、常に完全なコールチェーンを含みます。

呼び出された関数はtry-catchブロックで囲まれていることを知る必要はなく、コールチェーンを含むExceptionオブジェクトを作成し、呼び出しメソッドに渡します。このメソッドは、あるcatch節によってキャッチされるか、それをさらに継承するので、例外を処理するかどうかを判断する必要があります。呼び出しチェーンの一番上に到達し、VMがそれらを処理するまで、通常はスタックトレースを出力して終了するまで、バブルアップしない例外があります。

e.getMessageについて - 完全なスタック情報は元の例外にのみ含まれています。与えられた例では、元のExceptionオブジェクトeは破棄され、含まれているメッセージのみが新しく作成されたExceptionオブジェクトに渡されます。そしてその例外はそれ自身の呼び出しスタックを "知っている"だけなので、eに付加された元の情報は失われます。

0

下位レベルのメソッドは例外をスローし、上位レベルで処理する必要があります。あなたの例を考えてみましょう。それは好きなはずです。この

void top() { 
try { 
    f(); 
} catch (MyException ex) { 
    handleIt(); 
} finally { 
    cleanup(); 
} 
} 

void f() throws MyException { 
try{ 
    g(); 
}catch(MyException e){ 
    throws new MyException("Error in g()",e); 
} 

} 

void g() throws MyException{ 
throw new MyException(); 
} 
関連する問題