Advanced Java Services | UncaughtExceptionHandler |
Die Signatur von run() enthält keine throws-Klausel, wenn man weiß, daß eine Exception geworfen wird, kann man ein try-catch schreiben. Wenn aber unvorhergesehene Exceptions auftreten, dann wird der Thread mit einer Exception beendet und das führt dann zu einem Programmabbruch. Mit einem UncaughtExceptionHandler kann man hier ein sauberes Ende herbeiführen.
Mit dieser Methode kann man einen Handler übergeben, der für ein sauberes Ende sorgt. Per default ist kein Handler gesetzt. Thread.UncaughtExceptionHandler ist ein inneres Interface der Klasse Thread. Dieses Interface ist ein Functional Interface ( siehe Java1.8 ) und vereinbart daher nur eine Methode mit dem Namen void uncaughtException(Thread t, Throwable e). Ein gesetzter Handler verhindert einen Programmabbruch selbst wenn er leer ist oder wie im folgenden Beispiel nur aus Konsolmeldungen besteht.
Das Beispiel zeigt die Vorgehensweise.
Der Handler, der das Interface implementiert bringt in diesem Beispiel einige Informationen über den Thread und die Exception.
public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread th, Throwable ex) { System.out.println("uncaughtException() happened"); System.out.println("Thread = " + th ); System.out.println("Exception = " + ex); System.out.println("Threadstate: " + th.getState()); System.out.println("end UncaughtExceptionHandler"); } }
Das Runnable mit einem run(), das eine RuntimeException auslöst.
public class MyRunnable implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + " started, will throw an Exception in 3 seconds"); try{ TimeUnit.SECONDS.sleep(3); } catch(InterruptedException ex) { } String s = "abc"; Integer.parseInt(s); // löst die RuntimeException aus System.out.println("end run"); // wird nicht passieren } }
Das Main-programm setzt den Handler, startet den Thread und wartet auf seine Beendigung
public static void main(String[] args) { Thread th = new Thread( new MyRunnable() ); // setzen des handlers // der handler meldet die exception und gibt infos darüber th.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler() ); th.start(); System.out.println("MyRunnable gestartet."); try { th.join(); } catch(InterruptedException ex) { ex.printStackTrace(); } System.out.println("end main"); }
Ablauf
MyRunnable gestartet. Thread-0 started, will throw an Exception in 3 seconds uncaughtException() happened Thread = Thread[Thread-0,5,main] Exception = java.lang.NumberFormatException: For input string: "abc" Threadstate: RUNNABLE end UncaughtExceptionHandler end main
Kommentiert man die Zeile, in der der Handler gesetzt wird (*) aus, so ergibt sich folgender Ablauf
MyRunnable gestartet. Thread-0 started, will throw an Exception in 3 seconds Exception in thread "Thread-0" end main java.lang.NumberFormatException: For input string: "abc" at java.lang.NumberFormatException.forInputString(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at MyRunnable.run(MyRunnable.java:16) at java.lang.Thread.run(Unknown Source)
Man sieht deutlich, daß die Exception zum Programmabbruch führt.