Java 中如何记录未捕获的异常?

Java 记录未捕获异常:实现 Thread.UncaughtExceptionHandler 接口并设为默认处理器,所有未被 try-catch 捕获的异常都会触发记录。本文给出完整实现。

最佳实践
Java 中如何记录未捕获的异常?封面

核心:实现 Thread.UncaughtExceptionHandler 接口,在 uncaughtException() 方法中用日志框架记录异常,然后通过 Thread.setDefaultUncaughtExceptionHandler() 注册为全局默认处理器。

完整实现

import java.util.logging.Level;
import java.util.logging.Logger;

public class GlobalExceptionHandler implements Thread.UncaughtExceptionHandler {
    private static final Logger LOGGER = Logger.getLogger(GlobalExceptionHandler.class.getName());

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        LOGGER.log(Level.SEVERE, "线程 " + t.getName() + " 中出现未捕获异常", e);
    }
}

在程序入口注册:

public class Main {
    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler(new GlobalExceptionHandler());

        // 正常业务逻辑...
    }
}

此后任何线程中未被 catch 的异常都会触发 uncaughtException() 方法。

对单个线程设置

Thread thread = new Thread(() -> {
    throw new RuntimeException("出错了");
});
thread.setUncaughtExceptionHandler((t, e) -> {
    System.err.println("线程 " + t.getName() + " 异常: " + e.getMessage());
});
thread.start();

线程池中的注意事项

ThreadPoolExecutorexecute() 提交的 Runnable 抛出的异常会走 UncaughtExceptionHandler;但 submit() 返回的 Future 中的异常不会——它被封装在 Future 里,调用 get() 时才抛出。

观测云对照

生产环境推荐用观测云 APM 的 Java 探针,自动捕获未处理异常并关联到具体的请求 Trace,包含完整的堆栈和上下文信息,在观测云控制台中聚合展示和告警。

常见问题(FAQ)

Q:Spring Boot 项目需要手动注册吗?
A:Spring Boot 的 @ControllerAdvice + @ExceptionHandler 处理 Controller 层的异常;非 Web 层的异常仍建议注册全局 UncaughtExceptionHandler。

Q:捕获后进程会退出吗?
A:取决于 JVM 配置。默认情况下主线程的未捕获异常会导致进程退出,非守护线程的异常只导致该线程终止。

Q:log4j2/SLF4J 怎么用?
A:把上面示例中的 java.util.logging 替换为你项目使用的日志框架即可,逻辑不变。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台