Uncaught Exception Handling and ThreadDeath

Java uses (or in more specific terms, throws) exceptions to notify exceptional situations in programs. Developers write try-catch blocks to handle these exceptions, or simply propagate the exceptions upwards in the call stack.

An uncaught exception is a Throwable, which is not caught by any part of the application in the call stack where the exception occurred. It has propagated through the call stack, and has arrived at the underlying thread (could be the main thread or a defined thread), without being caught. Java actually handles uncaught exceptions according to the thread in which they occur. When an uncaught exception occurs in a particular thread, Java looks for what is called an uncaught exception handler, actually an implementaiton of the interface UnCaughtExceptionHandler.

The specific procedure is as follows. When an uncaught exception occurs, the JVM does the following:

  • it calls a special private method, dispatchUncaughtException(), on the Thread class in which the exception occurs;
  • it then terminates the thread in which the exception occurred

The dispatchUncaughtException() method, in turn, calls the thread’s getUncaughtExceptionHandler() method to find out the appropriate uncaught exception handler to use. Normally, this will actually be the thread’s parent ThreadGroup, whose handleException() method by default will print the stack trace.


package java.lang;

public class Thread implements Runnable {
     /**
     * Dispatch an uncaught exception to the handler. This method is
     * intended to be called only by the JVM.
     */
    private void dispatchUncaughtException(Throwable e) {
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }
}

public class ThreadGroup implements Thread.UncaughtExceptionHandler {
     ………
     public void uncaughtException(Thread t, Throwable e) {
	if (parent != null) {
	    parent.uncaughtException(t, e);
	} else {
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
		System.err.print("Exception in thread \""
				 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }
}

ThreadDeath – Silent Error

A throwable which extends ThreadDeath is silent as it is deadly. 😉


public static void main(String ... args) {
    throw new MyThrowable();
}

class MyThrowable extends ThreadDeath {

}

When this runs, no error/exception is printed, the thread just exits. This is because the above default implementation of UncaughtExceptionHandler ignores an instanceOf ThreadDeath.

The ThreadDeath error is used by Thread.stop() and although this method is deprecated, the ThreadDeath error is not deprecated and even describes itself as a “normal occurrence” 😉

Implementing UncaughtExceptionHandler

We can override this default behavior by providing our own uncaught exception handler, by extending the Thread.UncaughtExceptionHandler interface.

The interface requires us to implement a single method, as follows.


public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
      public void uncaughtException(Thread t, Throwable e) {
          // Write the custom logic here
      }
}

There are three places where this custom handler can be plugged in.

1. As the handler for a particular thread

When an uncaught exception occurs, the JVM initially looks for a handler registered for the particular thread. This can be set using Thread class method, public void setUncaughtExceptionHandler(handler) as in the following example.


public class MyRunnable implements Runnable {
      public void run() {
         // Other Code
         Thread.currentThread().setUncaughtExceptionHandler(myHandler);
         // Other Code
      }
}

2. As the handler for a particular thread group

If the thread belongs to a thread group, then the JVM attempts to invoke the handler for the thread group, if no thread level handler was specified (as in Option 1).

ThreadGroup class implements the Thread.UncaughtExceptionHandler interface. So we need to subclass the ThreadGroup class to provide an alternative implementation.

3. As the default handler for the application (JVM)

The default thread handler will be invoked by the JVM if no handler is present by any of the above steps. To set the default handler, Thread class provides a static method, which can be used as follows.

Thread.setDefaultUncaughtExceptionHandler(myHandler);

If none of the above are available, then the JVM delegates to its default behavior, writing to system error as specified in the ThreadGroup class. This is because main thread also belongs to the ‘main’ ThreadGroup, which uses the default implementation.

The uncaught exception handlers are useful in scenarios where certain actions should be taken when a failure occurs in the application, such as notifying to a particular email address, or to log to a specific file. Instead of writing try-catch blocks to cover such scenarios, a better solution would be to implement an Uncaught Exception Handler.

Advertisement

Posted on September 11, 2011, in java and tagged . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: