Thread.UncaughtExceptionHandler
states that when the method which handles uncaught exceptions itself throws an exception, that exception will be ignored:
void uncaughtException(Thread t, Throwable e):
Method invoked when the given thread terminates due to the given uncaught exception.
Any exception thrown by this method will be ignored by the Java Virtual Machine.
However when I tested it, the JVM did not ignore the exceptions handled by the uncaught exception handler`:
public static void main(final String args[]) {
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
throw new java.lang.RuntimeException("e2");
}
});
throw new RuntimeException("e1");
}
Eclipse Console output (JRE 1.7):
Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "main"
Another oddity I found out is that the output I get isn't coming from System.err
. It seems to be from another stream altogether. I verified this by redirecting System.err
to System.out
, but I'm still getting "red" output:
public static void main(final String[] args) {
System.setErr(System.out);
System.out.println(System.err == System.out);
System.err.println("this is black color");
try {
throw new Error("test stacktrace color");
} catch (Throwable e) {
e.printStackTrace();
}
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
throw new RuntimeException("from handler");
}
});
throw new RuntimeException("from main");
}
The output (bolded signifies red color):
true
this is black color
java.lang.Error: test stacktrace color at asf.df.main(df.java:13)
Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "main"
What's the explanation for these phenomenons?
What happens to errors thrown within UncaughtExceptionHandler? What's the expected (documented or guaranteed) behavior?
HotSpot JVM prints the exceptions thrown from the UncaughtExceptionHandler. See JavaThread::exit
if (HAS_PENDING_EXCEPTION) {
ResourceMark rm(this);
jio_fprintf(defaultStream::error_stream(),
"\nException: %s thrown from the UncaughtExceptionHandler"
" in thread \"%s\"\n",
pending_exception()->klass()->external_name(),
get_thread_name());
CLEAR_PENDING_EXCEPTION;
}
JVM prints these exceptions itself directly on stderr
regardless of the System.err
state - whether it was redirected or not.
Well, this kind of warning does not affect the application - in this sense the exception is "ignored". But you are right, this behavior is not obvious. Javadoc is misleading and is better to be fixed.
The exceptions are ignored and processing continues when thrown from a non-main thread.
If it is thrown in main the error code returned is non-zero.
The unhandled exceptions are logged via syserr.
public static void main(final String[] args) {
final Thread myThread = new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread()
.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread t, final Throwable e) {
System.out.println("In child UncaughtExceptionHandler at " + java.time.Instant.now());
throw new RuntimeException("From child thread UncaughtExceptionHandler"
+ java.time.Instant.now());
}
});
throw new RuntimeException("from runnable");
}
});
Thread.currentThread()
.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread t, final Throwable e) {
System.out.println("In main UncaughtExceptionHandler " + java.time.Instant.now());
throw new RuntimeException("From main thread UncaughtExceptionHandler" + java.time.Instant.now());
}
});
myThread.start();
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
System.out.println("After child thread: " + java.time.Instant.now());
//Will result in a non-zero return code
throw new RuntimeException("from main");
}
Output:
In child UncaughtExceptionHandler at 2014-07-19T04:10:46.184Z
Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "Thread-0" After child thread: 2014-07-19T04:10:48.197Z In main UncaughtExceptionHandler 2014-07-19T04:10:48.197Z
Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "main"
来源:https://stackoverflow.com/questions/24834702/do-errors-thrown-within-uncaughtexceptionhandler-get-swallowed