Java未捕获全局异常处理程序

ryoqjall  于 2023-05-27  发布在  Java
关注(0)|答案(4)|浏览(116)

我有一个应用程序,需要编写一个自定义的全局未捕获异常处理程序。我已经阅读了所有的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提供的例子,但我不知道如何实现它们,这就是这个问题的全部内容。
**更新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!");
    }
}

不用说,我得到了一堆错误与此。怎么会有课外活动呢?

**UPDATE 3:**这是最终有效的解决方案:

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

}
hmmo2u0o

hmmo2u0o1#

您可以为控制上面代码的线程设置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 docs for UncaughtExceptionHandler
当线程由于未捕获的异常而即将终止时,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!");
    }
}
ilmyapht

ilmyapht2#

可以使用UncaughtExceptionHandler处理导致线程突然终止的异常。UncaughtExceptionHandler的Java文档-
当线程由于未捕获的异常而突然终止时调用的处理程序的接口。当线程由于未捕获的异常而即将终止时,Java虚拟机将使用Thread.getUncaughtExceptionHandler()查询线程的UncaughtExceptionHandler,并将调用处理程序的uncaughtException方法,将线程和异常作为参数传递
您需要实现此接口,并使用方法setUncaughtExceptionHandler为线程设置UncaughtExceptionHandler的实现。有两种方法可以做到-

  1. setUncaughtExceptionHandler
  2. setDefaultUncaughtExceptionHandler
    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();
    }

}
kx7yvsdv

kx7yvsdv3#

Main.java

import static org.app.DefaultUncaughtExceptionHandler.registerDefaultUncaughtExceptionHandler;

static {
    registerDefaultUncaughtExceptionHandler();
}

DefaultUncaughtExceptionHandler.java

import java.lang.Thread.UncaughtExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @see ThreadGroup#uncaughtException(Thread, Throwable)
 */
public class DefaultUncaughtExceptionHandler implements UncaughtExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(DefaultUncaughtExceptionHandler.class);
    private static final UncaughtExceptionHandler parent;
    private static final DefaultUncaughtExceptionHandler instance;

    static {
        parent = Thread.getDefaultUncaughtExceptionHandler();
        instance = new DefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(instance);
    }

    public static final void registerDefaultUncaughtExceptionHandler() {
        // registered
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        if (!(e instanceof ThreadDeath))
            logger.error("Exception in thread \"" + t.getName() + "\" ", e);
        if (parent != null)
            parent.uncaughtException(t, e);
    }
}
pcww981p

pcww981p4#

您可以尝试设置自己的未捕获异常处理程序,但我强烈建议不要这样做。如果您的应用程序有可能中断的部分,并且如果在代码中断的位置没有正确处理该异常,则整个程序将频繁发生故障。

相关问题