views:

395

answers:

7

What is according to you the simplest way to intercept all exceptions in a Java application? Would AOP be needed to provide this kind of functionality or can it be done with dynamic proxies or is there another way? Is the simplest solution also a good solution regarding impact on execution performance? I would like to hear possible solutions from more experienced developers as I'm trying to grasp the technical know-how about the subject.

EDIT:

Thanks for the good advice already, but doesn't the current advice only apply to checked exceptions? What about unchecked exceptions, like NullPointerExceptions, wouldn't it be useful if these could be caught and that the application on catching them dumps the heap/stack to provide you with the current context of the application at the moment of crashing?

+3  A: 
public static void main(String[] args) {
    try {
        ...
    catch(Throwable t) {
        ...
    }
}
Nate
Taylor L's solution is actually better if you are using Java 5+ - this can't catch exceptions outside the main thread.
Nate
I agree with Nate. :-)
Taylor Leese
What if an exception occurs in a different thread?
Steve Kuo
+11  A: 

What is the purpose of you wanting to intercept every exception - for logging, error reporting?

Intercepting every single exception in every single line of a Java program is possible, but would probably incur quite a performance hit. If it's unavoidable, it'd probably be best to use something like AspectJ, which can run at compile-time (i.e. it "weaves" into your class files) and as such is much faster than dynamic proxies.

But it's something I would try to avoid doing at all costs! In general I would say it's better to limit the scope of the exceptions you want to catch. Also you might want to look into Thread.setDefaultUncaughtExceptionHandler, which I find useful for displaying error dialogs in GUI applications.

Phill Sacre
Sound advice, I would say. Glad someone pointed out AOP too.
Noldorin
A: 

More importantly than simply catching all exceptions is WHERE you catch the exception:

  1. Don't catch an exception unless you can do something about it. If you can't do anything about it, either let it bubble up to the next level or catch it, re-wrap it as a more specific exception and re-throw it.

  2. Always have a global exception handling block (like in Nate's answer) to catch any errors you can't handle anywhere so you can fail somewhat gracefully.

Eric Petroelje
A: 

If you simply want to catch an Exception, a try/catch block will suffice. If you want to prevent them being thrown or do some logging or wrapping of the Exception, you will probably need some AOP to do this. AspectJ will handle it pretty well, but beware of potential performance bottlenecks.

Dynamic proxies will only work when the method is proxied, so if any Exception is thrown and caught inside the execution of the proxy object there is no means for the proxies to intercept the Exception.

One thing to consider is if you are catching all exceptions, or only checked exceptions. To catch all exceptions, AspectJ's around throwing or after throwing advice would weave some processing around every method, this involves the creation of JoinPoint objects and synthetic methods at every method invocation. This is not normally a problem unless the process is in a tight loop, where the garbage collection can go through the roof.

Rich Seller
+7  A: 

Similar to Phil's answer, here is some sample code showing how to use the uncaught exception handler. This works for both checked and unchecked exceptions.

Edit: Updated to print the stack trace based on updated comments in the question.

import java.lang.Thread.UncaughtExceptionHandler;

public class Test {

    public static void main(String[] args) throws Exception {
     Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {

      @Override
      public void uncaughtException(Thread t, Throwable e) {
       e.printStackTrace();
      }}

     );

        // throw new RuntimeException(); /* this works too */
     throw new Exception();
    }

}
Taylor Leese
I actually never heard of this new functionality in Java 5 before.
nkr1pt
+2  A: 

At Nate and Konamiman... What you're suggesting does not work at all and does not answer the OP's question.

What if the OP starts a new thread from inside your try/catch?

For example:

public static void main(String[] args) {
    try {
        final Thread t = new Thread( new Runnable() {
            public void run() {
                System.out.println( 3 / Math.min(0,4) );
            }
        } );
        t.start();
    catch(Throwable t) {
        ...
    }
}

Then you're not catching the exception.

The correct way to do it is to use Thread.setDefaultUncaughtExceptionHandler.

AlexPat
yes - forgot about that.
Nate
As I said I don't know much about Java (so probably I shouldn't have answered, then). Anyway it's nice to learn something new.
Konamiman
(As this is not a forum, please note that answers might not be shown in the order in which they were posted.)
Arjan
A: 

To all those questionning the need to catch all exceptions...

There are a lot of valid reasons to catch all exceptions:

  • someone mentionned displaying a dialog in a GUI app telling about the problem
  • working around bugs in a 3rd party API you really need
  • working around bugs in some JVM implementation
  • self-healing software.
  • automatic online exception reporting.

Note that Java itself does intercept all exceptions on the EDT (Event Dispatch Thread) and spawns a new EDT when the EDT dies. You can consider that a form of "self-healing" software. The EDT dying is not something unheard of and doesn't exactly prevent the applications from running correctly (on the contrary). (and, yup, Swing and AWT have quite some bugs, just take a look at the Sun bug parade ;)

It could be argued that any self-respecting software should actually take into account the case of an unforeseen exception (are all the software you ship 100% bug free and never gets new releases, bug-fix releases?) and do something smart when such unforeseen exception happen.

The 'something smart' may be preventing the software from crashing (like in the EDT case), warning the user, sending a report, etc.

Answers questionning the need to do such a thing or suggesting that doing so is a bad practice should IMHO be modded down.

AlexPat