使用 log4j 在 Java 中记录运行时异常

Posted

技术标签:

【中文标题】使用 log4j 在 Java 中记录运行时异常【英文标题】:Log runtime Exceptions in Java using log4j 【发布时间】:2011-01-21 15:02:23 【问题描述】:

我目前正在使用 Tomcat、Spring 和 JAVA 构建应用程序。我使用Log4J 作为我的日志库。我目前正在将所有内容记录到文本文件中。我遇到的问题之一是RuntimeExceptions 没有被记录到任何文件中。我想知道是否有办法记录所有可能被扔到我的应用程序日志文件中的RuntimeExceptions。如果不是,是否可以将其记录到另一个日志文件?有没有标准的方法来做到这一点?如果是这样,在 Tomcat 中运行您的应用程序时是否有标准方法来执行此操作?

提前感谢您的帮助!

【问题讨论】:

你的意思是“未捕获”的 RuntimeExceptions 吗? 是的,我的意思是“未捕获”的 RuntimeExceptions 【参考方案1】:

我不确定这是否是您要查找的内容,但是有一个用于终止线程的异常的处理程序。它是线程目标未显式捕获的任何异常的处理程序。

默认的“未捕获异常处理程序”只是在Throwable 上调用printStackTrace() 以将堆栈跟踪打印到System.err。但是,您可以使用自己的 UncaughtExceptionHandler replace 来代替将异常记录到 log4j:

class Log4jBackstop implements Thread.UncaughtExceptionHandler 

  private static Logger log = Logger.getLogger(Log4jBackstop.class);

  public void uncaughtException(Thread t, Throwable ex) 
    log.error("Uncaught exception in thread: " + t.getName(), ex);
  


如果您正在使用向其传递Runnable 对象的执行器框架,则其线程可能具有自己的catch 块,以防止异常到达未捕获的异常处理程序。如果您想在那里捕获Runtime 异常,一种方法是将每个任务包装在日志包装器中,如下所示:

class Log4jWrapper 

  private final Logger log;

  private final Runnable target;

  Log4jWrapper(Logger log, Runnable target)  
    this.log = Objects.requireNonNull(log);
    this.target = Objects.requireNonNull(target); 
  

  public void run() 
    try 
      target.run();
     catch(RuntimeException ex) 
      log.error("Uncaught exception.", ex);
      throw ex;
    
  



...

Runnable realTask = ...;
executor.submit(new Log4jWrapper(Logger.getLogger(Whatever.class), realTask));

【讨论】:

这通常是如何在应用程序中处理此 RuntimeExceptions 的吗?我想我想知道这是否是处理此问题的标准方法。 另外我正在使用 Spring API 中的 ThreadPoolTask​​Executor,这仍然可以使用此类完成吗? 如果 Runnable 上有一个 RuntimeException,这很好用,但是如果 ThreadPoolTask​​Executor 有一个异常怎么办?假设它抛出一个 RunTimeException 因为池配置正确....这仍然会打印到控制台并且不会被记录....有什么建议吗? 您可能需要UncaughtExceptionHandlerRunnable 包装器。未捕获的异常处理程序将设置在创建和初始化执行程序并提交任务以执行的应用程序线程上。包装器用于提交的任务。 Spring 愚蠢地将运行时异常与检查异常混为一谈,因此帮助它摆脱混乱的解决方案可能并不漂亮。【参考方案2】:

记录未捕获的 RuntimeExceptions(或任何未捕获的 Throwables)的一种方法是创建一个实现 Thread.UncaughtExceptionHandler 的类。此类的uncaughtException() 方法只会将异常详细信息写入日志。每当未捕获的 RuntimeException 终止线程时,您可以通过添加以下行使 JVM 调用此异常处理程序

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());

到您的代码。

【讨论】:

我应该把那行代码Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());放在哪里?【参考方案3】:

您可以尝试重定向 StdErr 以使用您的记录器。这应该输出任何写入 std err 的结果(应该包括未处理的异常)

这篇博文很好地介绍了如何重定向到作为记录器一部分的 FileHandler:

Redirecting System.out and System.err to a rolling log file (Nick Stephen's blog)

【讨论】:

以上是关于使用 log4j 在 Java 中记录运行时异常的主要内容,如果未能解决你的问题,请参考以下文章

异常处理——把异常记录下来,log4j的使用

logback运行时异常怎么记录

JAVA中的异常处理及日志(log4j为例)的使用

运行我的测试日志记录代码时,我得到一个窗口,上面写着“发生了 Java 异常”

处理错误/异常并将它们记录在 iPhone 应用程序中

java中,想记录异常信息,该如何获得发生异常的类名和方法名呢?不要用log4j等。