我有一个应用程序,需要编写一个自定义的全局未捕获异常处理程序。我已经阅读了所有的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();
}
它抛出一个标准异常,它只是一个标准输出。我如何实现我自己的异常,通过将错误输出到日志文件中的简单方法覆盖标准异常?显然,实际的应用程序要大得多,我们正在谈论未捕获的异常,这就是为什么try / catch块不是选项。
更新:如果你能用一个非常明确的完整例子来回答,因为我找到了几个像@RamonBoza提供的例子,但我不知道如何实现它们,这是什么这个问题就是关于。
UPDATE2:所以我试着在下面的答案中测试唯一的例子,它显然不起作用。我创建了一个新的类文件“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
}
答案 0 :(得分:26)
您可以为控制上述代码的线程设置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);
}
});
的Java文档
当一个线程由于未捕获的异常而即将终止时 Java虚拟机将在线程中查询它 使用Thread.getUncaughtExceptionHandler()的UncaughtExceptionHandler 并将调用处理程序的uncaughtException方法,并传递 线程和异常作为参数
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!");
}
}
答案 1 :(得分:4)
您可以使用UncaughtExceptionHandler来处理导致线程突然终止的异常。 UncaughtExceptionHandler的Java文档 -
当线程突然终止到期时调用的处理程序的接口 一个未被捕获的例外。当线程由于未捕获的异常而即将终止时,Java虚拟机将使用Thread.getUncaughtExceptionHandler()向线程查询其UncaughtExceptionHandler,并将调用处理程序的uncaughtException方法,将线程和异常作为参数传递
您需要使用方法setUncaughtExceptionHandler实现此接口并为线程设置UncaughtExceptionHandler的实现。 有两种方法可以做到这一点 -
1)setUncaughtExceptionHandler - 这将是一个特定于线程的异常处理程序。因此,如果此线程被某些未处理的异常终止,则将使用此处理程序。
2)setDefaultUncaughtExceptionHandler - 如果没有针对某个线程的特定未捕获异常处理程序,这将是一个默认的异常处理程序。
示例 -
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();
}
}
答案 2 :(得分:1)
您可以尝试setting your own uncaught Exception handler,但我强烈反对。如果您的应用程序包含可能会破坏的部分,并且如果该代码在 代码中断时未正确处理,则整个程序将经常出现故障。