How uncaught exceptions are handled
In our discussion of unchecked exceptions, we mentioned
that when these exceptions are not caught in a try/catch block,
then what you often see in practice is Java print the exception stack trace and then terminate
your program. In reality, this is a simplistic view of what happens, and we'll look in more detail here.
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 latter interface has a method handleException(),
which the implementer overrides to take appropriate action, such as printing the stack trace to the
console. As we'll see in a moment, we can actually install our own instance of
UncaughtExceptionHandler to handle uncaught exceptions of a particular thread, or even
for the whole system.
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 occurred1.
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.
However, we can actually override this process for an individual thread, for a ThreadGroup,
or for all threads, as follows:
Which threads' handler to set | How to set | Notes |
All | Thread.setDefaultUncaughtExceptionHandler() | Relies on a ThreadGroup's uncaughtException() method not being overridden, or on any overriding implementation checking for the default handler. |
All for a particular thread group | Override ThreadGroup.uncaughtException() | Means you have to provide a ThreadGroup subclass. |
Individual thread | Thread.setUncaughtExceptionHandler() | If you're using your own Thread subclass, you could also override getUncaughtExceptionHandler() |
Thus, the full process used to determine which uncaught exception handler is called
is shown in Figure 2 below:
Figure 2: Process by which Java decides on which uncaught exception handler to call for a given thread.
As mentioned above, care must be taken to prevent uncaught exceptions from terminating
vital threads (or compensating for thread termination).
On the next page, we look at a special case of uncaught
exceptions in the event dispatch thread, where the Java runtime includes code to
start a new event dispatch thread when the old one dies.
1. In some cases, you therefore have to be careful to make sure that an uncaught
exception doesn't terminate an important thread unexpectedly. For example, an uncaught exception
in the thread that handles JavaSound MIDI events will terminate the MIDI event handling
thread and prevent further MIDI events from being processed.
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.