CLR(C#、VB.NETなどで使用されるランタイム)には、未処理の例外がスローされたときに呼び出されるコールバックを登録する方法があります。
Javaに似たようなものはありますか?
おそらく、単一のメソッドで何らかのインターフェイスを実装するオブジェクトを渡すAPIになると思います。例外がスローcatch
され、スタックに一致するものがない場合、ランタイムは登録されたオブジェクトのメソッドを呼び出し、例外オブジェクトが渡されます。
これにより、プログラマーはスタックトレースを保存できます。また、未処理の例外に対してのみ実行されるブロックSystem.exit
を停止するために、を呼び出すこともできます。finally
アップデート1。
これを説明するために、C#のサンプルを次に示します。
// register custom handler for unhandled exceptions
AppDomain.CurrentDomain.UnhandledException += (sender, evt) =>
{
Console.WriteLine("unhandled exception");
Environment.FailFast(null);
};
try
{
throw new NullReferenceException();
}
finally
{
Console.WriteLine("finally is executing");
}
重要なのは、私に電話をかけることで、ブロックの実行Environment.FailFast(null)
を停止できるということです。finally
案の定、Windows7で実行されているNET3.5および4.0では、出力に「finallyisexecuting」という文字列が表示されません。FailFast
しかし、呼び出しをコメントアウトすると、出力にその文字列が表示されます。
アップデート2。
これまでの回答に基づいて、これをJavaで再現する試みを示します。
// register custom handler for unhandled exceptions
Thread.currentThread().setUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
public void uncaughtException(
final Thread t, final Throwable e) {
System.out.println("Uncaught exception");
System.exit(0);
}
}
);
try
{
throw new NullPointerException();
}
finally
{
System.out.println("finally is executing");
}
これをJava6(1.6.0_18)で実行すると、次のように表示されます。
- ついに実行中
- 捕捉されなかった例外
つまり、JREはfinally
、キャッチされない例外ハンドラーを実行する前にブロックを実行します。
これが重要である理由の背景については、より複雑な例を次に示します。
try
{
try
{
throw new NullPointerException();
}
finally
{
System.out.println("finally is executing");
throw new java.io.IOException();
}
}
catch (java.io.IOException x)
{
System.out.println("caught IOException");
}
System.out.println("program keeps running as if nothing had happened...");
したがって、重大なバグがあり、プログラムを停止してスタックトレースをログに記録したいと思います。しかし、これを行う前に、スタックのどこかに中間finally
ブロックがあり(実際のプログラムでは、別のメソッドになります)、ファイルシステムにアクセスしようとします。何かがおかしい。次に、スタックの少し上に、IOException
私にとって大したことではないので、私がキャッチを持っていると仮定します。
言うまでもなく、出力は次のとおりです。
- ついに実行中
- IOExceptionをキャッチしました
- プログラムは何も起こらなかったかのように実行し続けます...
だから今、私は偶然に深刻なバグが私から隠されている状況を作り出しました。
2つの解決策があります:
- どういうわけか、ブロックが安全かどうかをローカルで判断できないため、
finally
ブロックがスローされないようにします。通常の実行パスをスローしても問題がないため、これは残念です。つまり、前の例外に応答して実行されていない場合です。 finally
キャッチされない例外がある場合にブロックを実行したくないことをランタイムに通知します。
後者が利用可能であれば、確かに私の好みです。