Java 5 Global Exception Handling

Ever since Java 5 came out, many articles and blog posts have been written talking about the new features. Just recently, however, I came upon a feature new to Java 5 that I had never seen mentioned in any of the articles I read: global exception handling.

There is a way to set a default handler for any exceptions that are thrown which are not caught. This is very handy for adding handlers for RuntimeExceptions, since they are unchecked and the compiler will not tell you to catch them.

For example, you may want to write a handler that will catch any NullPointerException, and e-mail the development team to let them know someone has made a coding mistake. There are many useful purposes for this feature. It should also be noted, however, that it breaks the idea of capturing an exception as close to the point of origin as possible. You should try to keep exception handling close to the exception, so that you have as much contextual information as possible to deal with the error and recover from it gracefully.

There is no denying, though, that we all write empty catch blocks, or catch blocks that print a trace to a log file and ignore it. For those, this is handy.

Below is an example that shows a simple default handler that catches an exception in the application, as well as one in an unrelated child thread.

//ExceptionHandlerExample.java
package com.air0day.machetejuggling;

public class ExceptionHandlerExample {
  public static void main(String[] args) throws Exception {

    Handler handler = new Handler();
    Thread.setDefaultUncaughtExceptionHandler(handler);

    Thread t = new Thread(new SomeThread(), "Some Thread");
    t.start();

    Thread.sleep(100);

    throw new RuntimeException("Thrown from Main");
  }

}

class Handler implements Thread.UncaughtExceptionHandler {
  public void uncaughtException(Thread t, Throwable e) {
    System.out.println("Throwable: " + e.getMessage());
    System.out.println(t.toString());
  }
}

class SomeThread implements Runnable {
  public void run() {
    throw new RuntimeException("Thrown From Thread");
  }
}

This example uses setDefaultUncaughtExceptionHandler, which sets it globally for all Threads (and yes, your main application runs as a Thread). There is also setUncaughtExceptionHandler, which is not a static method and applies to a specific thread.


3 Comments

  1. Rogerborg:

    I’m far too busy screwing the arse off of my hot wife to learn much Java, but I thought that it was firmly entrenched in the GLOBALS == TEH EVILS camp. Isn’t this a bit, you know, non-thread safe?

    Also, it occurs to me anyone who’s not already wrapping the body of their main() or run() inside a try/catch is the sort of lazy pig who wouldn’t piss on their own leg if it were on fire, and so I’m not sure how giving them a different method to ignore really heals the World’s Pain.

  2. Rod:

    Rogerborg,

    There are a lot of things that are wrong with the code. I tried pretty hard to think of a good usage for why you’d use this instead of wrapping in a try/catch and the only thing I could really think of was if you have multiple entry points in your code but you want uncaught exceptions to be handled the same way through all of them. This is slightly more elegant, in this scenario, then making an class that you pass exception information to, and catching Throwable in all of your entry points, then passing it to that class.

    But yes, it does break the principle of encapsulation to a great extent (which is what the globals issue is about). I definitely wouldn’t recommend this in place of more traditional solutions except for a few very specific issues.

    I’m not making the post like a “hey, look at this cool feature” but a “hey, look at this feature that nobody seems to be talking about.” I certainly have no intention of using it.

  3. Grobregor:

    What if somebody has a logging system that needs to keep track of all exceptions? It is ok to fill the log by hand from catch clauses but what if there are still uncaught exceptions. The logging system wouldn’t know would it? And error tracking gets hard this way.

Leave a comment