32

I have an application and need to code a custom global uncaught exception handler. I've read all the stackoverflow threads and each one of them is just missing a clear and simple example of how this is to be implemented.

Consider this simple following example:

public static void log(String msg) throws Exception {

    String logPath = "/application/logs/java.log";

    Calendar c = new GregorianCalendar();
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String now = format.format(c.getTime());

    PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logPath, true)));
    out.println(now + "  " + msg);
    out.close();

}

It throws a standard exception which is just a standard output. How do I implement my own exception which overrides the standard one by something simple as outputing the error into a log file? Obviously the actual application is much larger and we're talking about uncaught exceptions, which is why try/catch blocks is not the option.

UPDATE: If you could please answer with a very clear full example, because I found dozens of examples like the one @RamonBoza provided, yet I have no idea how to implement them, which is what this question is all about.

UPDATE2: So I've tried to test the only example in the answer below, it obviously doesn't work. I've created a new class file "MyRunnable" and pasted the code in it:

package mypackage;

Thread t = new Thread(new MyRunnable());
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

    public void uncaughtException(Thread t, Throwable e) {
       LOGGER.error(t + " throws exception: " + e);
    }
});
t.start();

//outside that class
class MyRunnable implements Runnable(){
    public void run(){
        throw new RuntimeException("hey you!");
    }
}

Needless to say I get a bunch of errors with this. How can something be outside of class anyway?

UPDATE3: This is the solution that finally works:

package mypackage;

public class MyClass {

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

        Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
            public void uncaughtException(Thread t, Throwable e) { 
                StringWriter sw = new StringWriter();
                e.printStackTrace(new PrintWriter(sw));
                String stacktrace = sw.toString();
                System.out.println(stacktrace);
            }
        });     

        //main method code

    }

    //Rest of the methods here

}
4

3 回答 3

31

You can set UncaughtExceptionHandler for the thread controlling the code above:

// t is the parent code thread
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

    public void uncaughtException(Thread t, Throwable e) {
       LOGGER.error(t + " throws exception: " + e);
    }
 });

Java docs for UncaughtExceptionHandler -

When a thread is about to terminate due to an uncaught exception the Java Virtual Machine will query the thread for its UncaughtExceptionHandler using Thread.getUncaughtExceptionHandler() and will invoke the handler's uncaughtException method, passing the thread and the exception as arguments

the setUncaughtExceptionHandler is commonly used to free memory or kill threads that the system will not be able to kill, and perhaps, remain zombie.

A real example:

Thread t = new Thread(new MyRunnable());
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

    public void uncaughtException(Thread t, Throwable e) {
       LOGGER.error(t + " throws exception: " + e);
    }
});
t.start();

//outside that class
class MyRunnable implements Runnable(){
    public void run(){
        throw new RuntimeException("hey you!");
    }
}
于 2013-10-17T09:11:09.293 回答
5

You can use UncaughtExceptionHandler to handle the exception those causes a thread to terminate abruptly. Java doc for UncaughtExceptionHandler -

Interface for handlers invoked when a Thread abruptly terminates due to an uncaught exception. When a thread is about to terminate due to an uncaught exception the Java Virtual Machine will query the thread for its UncaughtExceptionHandler using Thread.getUncaughtExceptionHandler() and will invoke the handler's uncaughtException method, passing the thread and the exception as arguments

You need to implement this interface and set your implementation of UncaughtExceptionHandler for a thread by using method setUncaughtExceptionHandler. There are two ways you can do this -

  1. setUncaughtExceptionHandler
  2. setDefaultUncaughtExceptionHandler

1) setUncaughtExceptionHandler - This will be a thread specific exception handler. So in case this thread gets terminated by some unhandled exception, this handler will be used.

2) setDefaultUncaughtExceptionHandler - This will be a default exception handler in case there is no specific uncaught exception handler for a thread.

Example -

class MyExceptionHandler implements UncaughtExceptionHandler{
    @Override
    public void uncaughtException(Thread arg0, Throwable arg1) {
        System.out.println("[DEFAULT EXCEPTION HANDLER] Caught some exception");
    }
}

class MyThread extends Thread{
    public MyThread() {
        setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("[THREAD SPECIFIC] My exception handler");
            }
        });
    }
    public void run(){
        throw new RuntimeException();
    }
}

public class Test {

    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
        new MyThread().start();
        // current thread does not have a thread specific exception handler
        throw new RuntimeException();
    }

}
于 2013-10-17T09:43:42.907 回答
-1

You can try setting your own uncaught Exception handler, however I strongly advise against it. If your application has parts that can potentially break and if that exception is then not properly handled at the location where your code breaks, your entire program will malfunction frequently.

于 2013-10-17T09:11:27.293 回答