java.lang.Thread.UncaughtExceptionHandler インタフェース
スレッドのエラーハンドリングためのインタフェース。
関連するThreadクラスのメソッド。
Interface for handlers invoked when a Thread abruptly terminates due to an uncaught exception.
public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
ちなみに、このインタフェースのメソッドと同じシグネチャのメソッド自体は、ThreadGroupクラスにはJDK 1.0時代から存在している。(ThreadGroup (Java 2 Platform SE 5.0))
このインタフェースの用途としては、今のところはアプリケーション専用のログに記録するとかしか思いつかないのだが、とりあえず(謎)動きを見てみる。
System.out.println("default uncaught exception handler: " + Thread.getDefaultUncaughtExceptionHandler()); System.out.println(" uncaught exception handler: " + Thread.currentThread().getUncaughtExceptionHandler()); System.out.println(" thread group: " + Thread.currentThread().getThreadGroup());
これをSunのJava VM(1.5.0_11)で実行すると、次のような出力が得られる。
default uncaught exception handler: null uncaught exception handler: java.lang.ThreadGroup[name=main,maxpri=10] thread group: java.lang.ThreadGroup[name=main,maxpri=10]
デフォルトのハンドラーはなく、所属するThreadGroup自体がそのスレッドのハンドラーになっている。ThreadGroupクラスのuncaughtException()メソッドのソースを見てみると、
- もし、親がいる場合は、親のuncaughtException()メソッドを呼ぶ。
- そうでなければ、デフォルトのハンドラーを取得する。
という動作をする。例外が発生したときにコンソールに出力されるスタックトレースはこの動作によって出力されるもの。
ということは、デフォルトのハンドラーだけを設定する:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { System.out.println("[default][" + Thread.currentThread().getName() + "][" + t.getName() + "]"); } }); Thread thread1 = new Thread() { public void run() { throw new RuntimeException("test"); } }; thread1.start();
と、デフォルトのハンドラーが呼び出される:
[default][Thread-0][Thread-0]
し、個別のハンドラーを設定する:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { System.out.println("[default][" + Thread.currentThread().getName() + "][" + t.getName() + "]"); } }); Thread thread1 = new Thread() { public void run() { throw new RuntimeException("test"); } }; thread1.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { System.out.println("[ custom][" + Thread.currentThread().getName() + "][" + t.getName() + "]"); } }); thread1.start();
と、個別のハンドラーが呼び出される。
[ custom][Thread-0][Thread-0]
しかし、パラメータとして渡されるスレッドと、Thread.currentThread()メソッドで取得するスレッドは同じなのだから、パラメータで渡す意味は何だろう、と考えてしまう。