Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use an uncaught exception handler for a multi-thread test in junit?

I have the following code that I expect to run successfully to completion but the code fails at the line "fail("this should not be reached");". Can someone please explain why the default uncaught exception handler is not called:

public class UncaughtExceptionTest extends TestCase
    implements UncaughtExceptionHandler {

    private final List<Throwable> uncaughtExceptions =
        new CopyOnWriteArrayList<Throwable>();

    class UncaughtExceptionTestInnerClass implements Runnable {
        private final ScheduledThreadPoolExecutor executor =
            new ScheduledThreadPoolExecutor(1);
        private final CountDownLatch latch;

        UncaughtExceptionTestInnerClass(CountDownLatch latch) {
            this.latch = latch;
            executor.schedule(this, 50, TimeUnit.MILLISECONDS);
        }

        @Override
        public void run() {
            System.out.println("This is printed");
            fail("this should fail");
            latch.countDown();
        }
    }

    @Test
    public void testUncaughtExceptions() {
        Thread.setDefaultUncaughtExceptionHandler(this);
        CountDownLatch latch = new CountDownLatch(1);
        UncaughtExceptionTestInnerClass testTheInnerClass =
                new UncaughtExceptionTestInnerClass(latch);
        try {
            if (!latch.await(1, TimeUnit.SECONDS)) {
                if (uncaughtExceptions.size() > 0) {
                    Throwable exception = uncaughtExceptions.get(0);
                    System.out.println("First uncaught exception: " + 
                                    exception.getMessage());
                }
                else {
                    fail("this should not be reached");
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        uncaughtExceptions.add(e);
    }
}
like image 381
BD at Rivenhill Avatar asked Jul 02 '10 03:07

BD at Rivenhill


People also ask

How do you handle exceptions in multithreading?

Exception handling in Thread : By default run() method doesn't throw any exception, so all checked exceptions inside the run method has to be caught and handled there only and for runtime exceptions we can use UncaughtExceptionHandler.

What is uncaught exception handler?

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.

How are uncaught exceptions handled?

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.

What is uncaught exception explain with example?

When an uncaught exception occurs, the JVM calls a special private method known dispatchUncaughtException( ), on the Thread class in which the exception occurs and terminates the thread. The Division by zero exception is one of the example for uncaught exceptions.


2 Answers

It has to do with the fact you're using an Executor to run the task. The uncaught exception handler is invoked only if the thread is about to be terminated due to an uncaught exception. If you change your implementation to use a plain thread so that the thread will terminate with the exception, you will see the expected behavior.

Depending on how you submit tasks, the executor thread may catch all Throwables and handle them. Therefore, the thread does not terminate due to these exceptions, and thus the uncaught exception handler does not get involved. For example, ThreadPoolExecutor.execute(Runnable) will trigger the uncaught exception handler. However, ThreadPoolExecutor.submit(Callable) does not. Also, ScheduledThreadPoolExecutor.schedule() does not either (it has to do with their use of FutureTask for implementation).

A better way of accessing unexpected exceptions with an executor service is via Future.

like image 129
sjlee Avatar answered Oct 05 '22 13:10

sjlee


ScheduledThreadPoolExecutor.schedule() takes a Runnable/Callable argument, not Thread. The former don't have runtime exception handlers. Have a try/catch block for a RuntimeException in your run or call method.

like image 40
Tim Cook Avatar answered Oct 05 '22 13:10

Tim Cook