Java未捕获全局exception处理程序

我有一个应用程序,需要编写自定义全局未捕获exception处理程序。 我已经阅读了所有的stackoverflow线程,并且每个线程都缺少一个如何实现它的简单明了的例子。

请考虑以下简单示例:

public static void log(String msg) throws Exception { String logPath = "/application/logs/java.log"; Calendar c = new GregorianCalendar(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String now = format.format(c.getTime()); PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logPath, true))); out.println(now + " " + msg); out.close(); } 

它抛出一个标准exception,它只是一个标准输出。 我如何实现我自己的exception,通过将错误输出到日志文件中的简单方法覆盖标准exception? 显然,实际的应用程序要大得多,我们正在谈论未捕获的exception,这就是为什么try / catch块不是选项。

更新:如果你能用一个非常明确的完整例子来回答,因为我发现了几个像@RamonBoza提供的例子,但我不知道如何实现它们,这就是这个问题的全部内容。

更新2:所以我试着在下面的答案中测试唯一的例子,它显然不起作用。 我创建了一个新的类文件“MyRunnable”并将代码粘贴到其中:

 package mypackage; Thread t = new Thread(new MyRunnable()); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { LOGGER.error(t + " throws exception: " + e); } }); t.start(); //outside that class class MyRunnable implements Runnable(){ public void run(){ throw new RuntimeException("hey you!"); } } 

不用说,我得到了一堆错误。 无论如何,有什么东西可以在课外?

UPDATE3:这是最终有效的解决方案:

 package mypackage; public class MyClass { public static void main(String[] args) throws Exception { Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); String stacktrace = sw.toString(); System.out.println(stacktrace); } }); //main method code } //Rest of the methods here } 

您可以为控制上述代码的线程设置UncaughtExceptionHandler:

 // t is the parent code thread t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { LOGGER.error(t + " throws exception: " + e); } }); 

UncaughtExceptionHandler的 Java文档 –

当线程由于未捕获的exception而即将终止时,Java虚拟机将使用Thread.getUncaughtExceptionHandler()向线程查询其UncaughtExceptionHandler,并将调用处理程序的uncaughtException方法,将线程和exception作为参数传递

setUncaughtExceptionHandler通常用于释放内存或杀死系统无法杀死的线程,也许还会保留僵尸。

一个真实的例子:

 Thread t = new Thread(new MyRunnable()); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { LOGGER.error(t + " throws exception: " + e); } }); t.start(); //outside that class class MyRunnable implements Runnable(){ public void run(){ throw new RuntimeException("hey you!"); } } 

您可以使用UncaughtExceptionHandler来处理导致线程突然终止的exception。 UncaughtExceptionHandler的Java文档 –

当线程因未捕获的exception而突然终止时调用的处理程序接口。 当线程由于未捕获的exception而即将终止时,Java虚拟机将使用Thread.getUncaughtExceptionHandler()向线程查询其UncaughtExceptionHandler,并将调用处理程序的uncaughtException方法,将线程和exception作为参数传递

您需要使用方法setUncaughtExceptionHandler实现此接口并为线程设置UncaughtExceptionHandler的实现。 有两种方法可以做到这一点 –

  1. setUncaughtExceptionHandler
  2. 是,setDefaultUncaughtExceptionHandler

1)setUncaughtExceptionHandler – 这将是一个特定于线程的exception处理程序。 因此,如果此线程被某些未处理的exception终止,则将使用此处理程序。

2)setDefaultUncaughtExceptionHandler – 如果没有针对线程的特定未捕获exception处理程序,这将是一个默认的exception处理程序。

示例 –

 class MyExceptionHandler implements UncaughtExceptionHandler{ @Override public void uncaughtException(Thread arg0, Throwable arg1) { System.out.println("[DEFAULT EXCEPTION HANDLER] Caught some exception"); } } class MyThread extends Thread{ public MyThread() { setUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("[THREAD SPECIFIC] My exception handler"); } }); } public void run(){ throw new RuntimeException(); } } public class Test { public static void main(String[] args) { Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler()); new MyThread().start(); // current thread does not have a thread specific exception handler throw new RuntimeException(); } } 

您可以尝试设置自己的未捕获的exception处理程序 ,但我强烈建议不要使用它。 如果您的应用程序包含可能会破坏的部分,并且如果您的代码中断的位置没有正确处理该exception,则整个程序将经常出现故障。