Get notified when an uncontrolled thread is killed

Sometimes the third party libraries we use may spawn different threads which are not directly under the control of our application, i.e. we don't have any reference to those thread objects.

When such threads die, the program doesn't necessarily get exited, but might malfunction i.e. the application is left in an undesirable state.

In this case, it is essential that we get notified about such cases and handle them in our application, for example, we can log the error and exit the program.

This can be done using an uncaught exception handler. The uncaught exception handler receives all uncaught exceptions in our application. Threads die abruptly if there is some exception which isn't handled.

Program

public class UncaughtExceptionHandlerDemo {
    public static void main(String args[]) {
    
        Thread.setDefaultUncaughtExceptionHandler((whichThread, whatException) -> {
            System.out.printf("Exception %s occurred on thread %s\n", whatException, whichThread);
            System.out.println("Exiting the program with status code 1");
            System.exit(1);
        });
      
      new Thread(UncaughtExceptionHandlerDemo::methodThatRaisesException,"ExceptionRaisingThread").start();
      new Thread(UncaughtExceptionHandlerDemo::methodThatDoesntRaiseException,"NoExceptionThread").start();
    }
    
    static void methodThatDoesntRaiseException() {
        for(int i=0;i<20;i++) {
            try {
                System.out.printf("%s -> %d\n", Thread.currentThread().getName(), i);
                Thread.sleep(500);
            } catch(InterruptedException ex) {
                
            }
        }
    }
    
    static void methodThatRaisesException() {
        for(int i=0;i<10;i++) {
            System.out.printf("%s -> %d\n", Thread.currentThread().getName(), i);
        }
        throw new RuntimeException("Test exception");
    }
}

Output & Explanation

ExceptionRaisingThread -> 0
NoExceptionThread -> 0
ExceptionRaisingThread -> 1
ExceptionRaisingThread -> 2
ExceptionRaisingThread -> 3
ExceptionRaisingThread -> 4
ExceptionRaisingThread -> 5
ExceptionRaisingThread -> 6
ExceptionRaisingThread -> 7
ExceptionRaisingThread -> 8
ExceptionRaisingThread -> 9
Exception java.lang.RuntimeException: Test exception occurred on thread Thread[ExceptionRaisingThread,5,main]
Exiting the program with status code 1

In the above program, there are two threads which execute the two methods methodThatRaisesException and methodThatDoesntRaiseException. Since the method that doesn't raise exception has a Thread.sleep(500) it will usually take time to complete. We know that unless all threads complete execution, our main thread will not be completed. So, our program runs till the main thread ends i.e. till all threads end.

The thread that calls methodThatRaisesException will obviously complete first and then, methodThatDoesntRaiseException will still go on.

Ideally, I don't want methodThatDoesntRaiseException or even the whole application to continue if methodThatRaisesException gets killed. So, the uncaught exception handler prints a message and then exits.

No comments: