I'm not sure if this is what you are looking for, but there is a handler for exceptions that terminate threads. It is a handler for any exception that is not caught explicitly by the target of the thread.
The default "uncaught exception handler" simply calls printStackTrace()
on the Throwable
to print the stack trace to System.err
. However, you could replace this with your own UncaughtExceptionHandler
that logs the exception to log4j instead:
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);
}
}
If you are using an executor framework to which you pass a Runnable
object, its threads probably have their own catch
block that prevent exceptions from reaching the uncaught exception handler. If you want to catch Runtime
exceptions there, one way to do it is to wrap each task in a logging wrapper, like this:
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));
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…