Uncaught exception handlers

An Uncaught Exception Handler in Java is a mechanism that allows you to define a global or per-thread strategy for dealing with uncaught exceptions — those that are not caught within the thread’s run() method. It is part of Java’s Thread API and is particularly useful in multi-threaded environments where uncaught exceptions would otherwise silently terminate a thread.

Why Use an Uncaught Exception Handler?

When a thread throws an exception and does not catch it, the thread dies — and unless you’ve set up an UncaughtExceptionHandler, that failure may go unnoticed, especially in production systems. By using this handler:

  • You can log the exception,

  • Alert monitoring systems,

  • Or restart threads/services if needed.

Syntax and Structure

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("Default handler caught exception in thread " + t.getName() + ": " + e);
    }
});
Code language: JavaScript (javascript)
Or per-thread:
Thread t = new Thread(() -> {
    throw new RuntimeException("Something went wrong!");
});

t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("Exception in thread " + t.getName() + ": " + e);
    }
});Code language: JavaScript (javascript)

How It Works

When a thread terminates due to an uncaught exception:

  1. Java checks if the thread has its own handler using t.getUncaughtExceptionHandler().

  2. If none is set, it checks the default handler via Thread.getDefaultUncaughtExceptionHandler().

  3. If that is also not set, the JVM handles it by printing the stack trace to stderr.

Example Program

public class UncaughtHandlerExample {
    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> {
            System.out.println("Caught by default handler: " + exception.getMessage());
        });

        Thread t1 = new Thread(() -> {
            throw new RuntimeException("Unhandled exception in t1");
        });

        Thread t2 = new Thread(() -> {
            throw new NullPointerException("Unhandled exception in t2");
        });

        t1.start();
        t2.start();
    }
}

Use Cases

  • Logging fatal thread crashes

  • Fail-safe recovery mechanisms

  • Graceful shutdown alerts

  • Integration with monitoring tools (e.g., Sentry, New Relic)

 Best Practices

Do Avoid
Use per-thread handlers for critical tasks Ignoring thread crashes
Log all uncaught exceptions with full stack trace Overloading handler with heavy logic
Use default handler for general fallback Restarting threads blindly without state checks

Uncaught exception handlers are a powerful feature in Java’s concurrency model that allow you to catch and process uncaught exceptions thrown by threads. They help improve error visibility, recovery, and system stability in concurrent applications.

Scroll to Top