UncaughtExceptionHandler changes exception message - java

Small example:
public class App {
public static void main(String[] args) {
throw new RuntimeException("Test exception");
}
}
Prints following as expected:
Exception in thread "main" java.lang.RuntimeException: Test exception
at App.main(App.java:5)
Lets modify this program:
public class App {
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof RuntimeException) throw (RuntimeException)e;
}
});
throw new RuntimeException("Test exception");
}
}
Prints:
Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "main"
Question:
Why message doesn't contain any information about where it occurs and there is no stack trace, message?
As for me exception message looks weird.

The Java API documentation says:
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.
So if you want the program to terminate on some exceptions and print their message/stacktrace you should do:
#Override
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof RuntimeException) {
e.printStackTrace();
System.exit(1);
}
}

Related

Exception in child thread

I am creating a new Thread from the main thread using the below:
public static void main(String[] args) {
try {
new TestThread().start();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Inside main");
}
And throwing an exception. I am able to catch it in the main thread also.But according to article
this shouldn't be the case right?
EDIT:
public class TestThread extends Thread {
#Override
public void run() {
throw new RuntimeException();
}
}
Exception Trace
Inside main
Exception in thread "Thread-0" java.lang.RuntimeException
at TestThread.run(TestThread.java:8)
Exceptions thrown by a thread's run() method, are not caught by the main thread but handled by the JVM.
If you want to manage this situation, you should use the Thread.setUncaughtExceptionHandler method.
Something like this:
class MyHandler implements Thread.UncaughtExceptionHandler
{
#Override
public void uncaughtException(Thread t, Throwable e)
{
System.out.println("Caught exception " + e.getMessage());
e.printStackTrace();
}
}
class MyThread extends Thread
{
public MyThread()
{
setUncaughtExceptionHandler(new MyHandler());
}
#Override
public void run()
{
throw new RuntimeException("ciao");
}
}
The article you refer to is "Java Thread: Run method cannot throw checked exception".
In Java, Thread's run method cannot throw checked exceptions because it would involve changing the signature of the run() method. However, in your example, you throw a RuntimeException, which isn't a checked exception. See Understanding checked vs unchecked exceptions in Java.
Note, however, that you are not actually catching the exception in the main thread: replace the printStackStrace statement with something like ...println("caught") for this to be more obvious.

tips "Unhandled exception type xxx" in eclipse

I don't think I understand the try-catch block and throws really.
public class TestException {
public static void main(String[] args) {
new TestException().tt();
}
public void tt() {
try {
throw new RuntimeException();
}catch (Exception e) {
throw e;
}
}
}
When in Eclipse, there is an error hint about 'Unhandled exception type xxx', and if you run this, you will get an
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type Exception
But in Idea, there's no errors. It runs and throws the exception correctly.
In my opnion, the 'e' was not declared as a RuntimeException(althrough it is an RuntimeException), so the tt() method must be declared with throws. But actually it's not. Why?
This should answer your question:
public class TestException {
public static void main(String[] args) {
new TestException().tt();
}
public void tt() {
try {
throw new RuntimeException();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
If you use throws, you tell those who use your function, "My function may throw exceptions. You have to handle that."
You should get difference of throws and throw in this sentence.
If you use try-catch, you handle that exception.
1) You should add throws keyword like below
public class TestException {
public static void main(String[] args) {
new TestException().tt();
}
public void tt() **throws Exception** {
try {
throw new RuntimeException();
}catch (Exception e) {
throw e;
}
}
}
2) Handle exception where you use function
public class TestException {
public static void main(String[] args) {
try{
new TestException().tt();
}catch(Exception e){
System.out.println("Error handled");
}
}
public void tt() throws Exception {
try {
throw new RuntimeException();
}catch (Exception e) {
throw e;
}
}
}
In general if you catch an exception you handle it. Like this
public class TestException {
public static void main(String[] args) {
new TestException().tt();
}
public void tt() {
try {
throw new RuntimeException();
}catch (Exception e) {
System.out.println("Error caught! ")
}
}
}
or
public class TestException {
public static void main(String[] args) {
try {
new TestException().tt();
}catch(Exception e){
System.out.println("Error caught! ")
}
}
public void tt() throws RuntimeException {
throw new RuntimeException();
}
}
You can also throw other's exception
public class TestException {
public static void main(String[] args) {
try{
new TestException().a();
}catch(Exception e){
System.out.println("Error handled");
}
}
public void a() throws Exception {
b();
}
public void b() throws Exception {
c();
}
public void c() throws Exception {
throw new RuntimeException();
}
}
I think that you want to look into 'Checked Exceptions' and 'Unchecked Exceptions'.
Only Checked Exceptions need to be declared in a methods signature, and RuntimeException is an unchecked exception (though you can declare it if you like - it just isn't necessary to compile).
https://docs.oracle.com/javase/7/docs/api/java/lang/Exception.html
The API for java Exception says:
"The class Exception and any subclasses that are not also subclasses of RuntimeException are checked exceptions. Checked exceptions need to be declared in a method or constructor's throws clause if they can be thrown by the execution of the method or constructor and propagate outside the method or constructor boundary"
https://docs.oracle.com/javase/7/docs/api/java/lang/RuntimeException.html
The API for java RuntimeException says:
"RuntimeException and its subclasses are unchecked exceptions. Unchecked exceptions do not need to be declared in a method or constructor's throws clause if they can be thrown by the execution of the method or constructor and propagate outside the method or constructor boundary."
In my opnion, the 'e' was not declared as a RuntimeException(althrough it is an RuntimeException), so the tt() method must be declared with throws. But actually it's not. Why?
Let's consider what we know:
When using rethrow syntax, the existing exception object (e) is rethrown.
e is an object of class Exception, or one of its subtypes.
RuntimeException is a subtype of exception, and is not compiled time checked, so it's possible the re-thrown object is a non compile time checked object.
The compiler cannot see a place where the code definitely, or even possibly throws a compile checked exception, and so it makes sense that it does not force those semantics.
For example, if you change your catch to an IOException, the compiler will not allow you to do that without a line in the try which could possibly lead to an IOException.
If you added such a line, then the compiler would recognize that the throw would rethrow a compile time checked exception, and make you catch it again, or mark the function with the appropriate throws clause.
As for eclipse, your code compiles OK in mine with my JDK.

Do errors thrown within UncaughtExceptionHandler get swallowed?

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"

Catching run time exceptions?

I know that RunTimeExceptions can be caught by Exception catch block as below.
public class Test {
public static void main(String[] args) {
try {
throw new RuntimeException("Bang");
} catch (Exception e) {
System.out.println("I caught: " + e);
}
}
}
I have my own created exception class as below.
public class CustomException extends Exception {
public CustomException(String message, Throwable cause) {
super(message, cause);
}
public CustomException(String message) {
super(message);
}
}
But now instead of keeping Exception in catch block, i kept CustomException.But run time exception is not caught by catch block now. Why?
public class Test {
public static void main(String[] args) {
try {
//consider here i have some logic and there is possibility that the logic might throw either runtime exception or Custom Exception
throw new RuntimeException("Bang");
} catch (CustomException e) {
System.out.println("I caught: " + e);
}
}
}
Thanks!
Extending Exception class does not make it is Runtime Exception. See above diagram. Also you can use polymorphic reference(superclass) to catch an subclass Exception. It does not work the other way around.
This is because CustomException is not a super class of RuntimeException. Because you are throwing RuntimeException, which is not the subclass of CustomException, the catch block is not catching it.

Java exception specification for the main method

Do we not need exception specification for the main method in a Java program. For example, the following code works exactly the same without specifying "throws Xcept" for the main method.
class Xcept extends Exception {
public Xcept(){
}
public Xcept(String msg){
super(msg);
}
}
public class MyException {
public void f() throws Xcept {
System.out.println("Exception from f()");
throw new Xcept("Simple Exception");
}
public static void main(String[] args) throws Xcept {
MyException sed = new MyException();
try {
sed.f();
} catch(Xcept e) {
e.printStackTrace();
}
finally {
System.out.println("Reached here");
}
}
}
I read that java enforces this, but I don't get a compile time error if I exclude this specification for the main method.
That's because Xcept will never be thrown out of your main method, as you actually catch it there... The sed.f() call may result in an Xcept being thrown, but it's caught and handled.

Categories