"Handle or declare. That's the law." - Head First
But, is it a good law? Let me give an example first:
public static void main(String[] args) throws Exception {
m1();
}
static void m1() throws Exception{
m2();
}
static void m2() throws Exception {
throw new Exception();
}
m2() throws exception and m1() calls m2(), meaning it must either handle or declare it. Hmmm let's declare it. Then main() calls m1() and it has same poll: declare or handle. I again decided to declare it and code compiles just fine.
Okay, it works, but who handled this exception at all? Looks like no one did. I know I am a beginner, but I don't like the sound of that. Yes, some methods can decide whether to declare or handle exceptions, but why main()? Shouldn't main method be one that just handles? In that way, no exception could "slip".
Am I missing something to this? I was honestly surprised that it is okay for main method to just declare exception, knowing that it is the last place we could technically catch something.
who handled this exception at all?
The Java runtime did.
More specifically, the UncaughtExceptionHandler did, as specified in the Java Language Specification (JLS), section 11.3. Run-Time Handling of an Exception:
If no catch clause that can handle an exception can be found, then the current thread (the thread that encountered the exception) is terminated. Before termination, all finally clauses are executed and the uncaught exception is handled according to the following rules:
If the current thread has an uncaught exception handler set, then that handler is executed.
Otherwise, the method uncaughtException is invoked for the ThreadGroup that is the parent of the current thread. If the ThreadGroup and its parent ThreadGroups do not override uncaughtException, then the default handler's uncaughtException method is invoked.
So, by default, when main() throws an exception, unchecked or checked, the built-in default "uncaught exception handler" will simply print the stacktrace to System.err, as-if the following was executed right before main() was called:
Thread.setDefaultUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler());
class DefaultUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread t, Throwable e) {
e.printStackTrace();
}
}
After the "uncaught exception handler" has been invoked the thread is terminated, same as if you simply return from the main() method, and unless the code has started non-daemon threads that are still running, the program ends.
Application may contain more than one class with main method. In that case application should declare a manifest to know which main is entrypoint (first called method). Main method can be called from another methods or another main method as a static method and can throw any exception. If you don't catch exception at least in entrypoint, then exception returned from your application to java virtual machine, then mashine deside what todo with exception. Usually jvm prints error message and return value other than 0 to operating system.
Related
When using a try / catch block, we can print the stack trace in the catch block using the e.printStacktrace() method.
In case of an unhandled exception the stack trace still gets printed.
Who prints that stack trace on the console? and how?
If an exception isn't caught explicitly in Java (by a catch block) in the code that you're looking at, then the following will happen:
The exception will propagate up the call stack until it finds another catch block to handle it. If so, great. If it gets to the top of the stack and there's no catch block to handle it, then:
It's handled by whatever is specified as the uncaught exception handler for that thread. This is a block of code that's explicitly set to run if this scenario occurs. If no handler is specified, then:
It will call uncaughtException() on ThreadGroup. As per its Javadoc, this does the following:
If this thread group has a parent thread group, the uncaughtException method of that parent is called with the same two arguments.
Otherwise, this method checks to see if there is a default uncaught exception handler installed, and if so, its uncaughtException method is called with the same two arguments.
Otherwise, this method determines if the Throwable argument is an instance of ThreadDeath. If so, nothing special is done. Otherwise, a message containing the thread's name, as returned from the thread's getName method, and a stack backtrace, using the Throwable's printStackTrace method, is printed to the standard error stream.
The bolding is mine, and that's the behaviour that's responsible, by default, for printing your stack trace.
As an aside, you can actually verify that last part if you so wish - something like this will print a (short) stack trace, as you'd expect:
public static void main(String[] args) throws Throwable {
throw new Throwable();
}
Exception in thread "main" java.lang.Throwable
at javaapplication6.JavaApplication6.main(JavaApplication6.java:18)
Yet as per the above docs, this doesn't print anything:
public static void main(String[] args) throws Throwable {
throw new ThreadDeath();
}
So I have some code that's throwing a RuntimeException. I know it's throwing a RuntimeException, I wrote it to do so under certain circumstances. Recently, I was having what I thought was a deadlock, because the method didn't seem to be finishing, but as I logged out the problem I realized that it was in fact that RuntimeException.
Now, here's the issue: This exception is occurring silently. The Android monitor in Android Studio isn't displaying a stack trace for it. This threw me off, because in normal Java applications (which I'm more used to, I'm a professional Java dev but I'm a bit new to Android), RuntimeExceptions send a stack trace directly to the console.
So, my reaction was to do a Thread.UncaughtExceptionHandler to log this. Only... it's not working.
Here's my UncaughtExceptionHandler. I don't actually care about it doing all the things it does, I was just trying to get something to happen to indicate that it was being called.
public static class ContactsUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{
private static final String TAG = "UncaughtException";
#Override
public void uncaughtException(Thread thread, Throwable throwable) {
System.out.println("UNCAUGHT EXCEPTION"); //TODO delete this
Log.e(TAG, String.format("Uncaught exception in thread %d", thread.getId()), throwable);
throwable.printStackTrace();
System.exit(1);
}
}
This handler is being added in the following ways:
1) I have an executor spawning threads. It uses a ThreadFactory, which assigns this handler to each thread using Thread.setUncaughtExceptionHandler().
2) I call Thread.setDefaultUncaughtExceptionHandler() in the onCreate() method of my Application class.
3) The code where this is occurring is a Runnable.run() method. I put a line in that run() method calling Thread.currentThread().setUncaughtExceptionHandler().
Nothing works. None of those operations there get triggered.
I know with 100% certainty that a RuntimeException is occurring, because if I surround the code with a try-catch block and do printStackTrace() that way, it shows up in the console log. I just can't get the UncaughtExceptionHandler to work.
The code where this is happening is very long and verbose, here's a quick summary of it:
#Override
public void run(){
Thread.currentThread().setUncaughtExceptionHandler(new ContactsThreadFactory.ContactsUncaughtExceptionHandler());
System.out.println("This line outputs to the console");
object.callingMethodThatCausesException();
System.out.println("This line never executes, because exception was thrown");
}
Any ideas on how to fix this? I don't understand why it's not working.
Edit: Just discovered something interesting, not 100% sure what it means yet. I put "throws new RuntimeException()" into the onCreate() method of my Activity class, and that exception showed up in the console like normal. I tried doing the same thing from within that Runnable, and nothing. Not entirely sure what to make of that.
Also, the UncaughtExceptionHandler worked for that new RuntimeException I put in. I just don't understand why it's not working elsewhere?
I have a thread that opens a socket at the beginning of its run method, after which it enters into a listening loop. I want the run method to throw a RuntimeException that tells me that the thread failed to start.
Is there such an exception type in Java? Something like ThreadStartFailedException?
Note: I don't want to open the socket in its constructor because I need this thread to be restartable, i.e. when I call interrupt on it, it gracefully closes its socket; if run is reinvoked on the same instance, the socket is recreated and the thread is running as if it were its first time.
Yes there is a RuntimeException class. But throwing exception from run method and if you need to catch it later outside of the run method and it's corresponding class context, you will need to use Callable instead of Runnable.
Is there such an exception type in Java? Something like
ThreadStartFailedException?
Nope, there is no such exception exists by default. Check the subclasses of RuntimeException from the documentation. You can subclass the RuntimeException if you want.
class ThreadStartFailedException extends RuntimeException
{
public ThreadStartFailedException(String message) {
super(message);
}
}
I was playing around with some of my code and came across something I didn't fully understand. I have a class called SentimentClassifier, the constructor of which looks like this:
public SentimentClassifier(final int nGramToBeUsed) {
try {
classifier = (DynamicLMClassifier<?>) AbstractExternalizable.readObject(new File(etc));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I have another class which creates this one, like so:
public TwitterManager(final int nGramToBeUsed) {
sentimentClassifier = new SentimentClassifier(nGramToBeUsed);
}
If I run the code like this, everything works fine. But if I change the first class from using try/catch to throw the exception, like so:
public SentimentClassifier(final int nGramToBeUsed) throws ClassNotFoundException, IOException {
classifier = (DynamicLMClassifier<?>) AbstractExternalizable.readObject(new File(etc));
}
Suddenly the second class complains that the IOException isn't being handled. Why is this thrown only for the thrown exception and not for the try/catch?
When you call a method M1 from another method M2:
If some code in M1 raises some Checked Exception, and the method M1 itself handles it, rather than throwing it, you don't have to worry about the exception while calling it.
Now, if the exception raised in M1, is not being handled in M1 itself, rather it is propagated up the stack trace, then M1 must declare that exception in the throws clause. This is just for the convenience of the calling method to know that it should be ready to handle those exception in case they are thrown. This is only the case with Checked Exception.
But if the calling method M2, doesn't handle that exception, it has the option to re-declare that exception to be thrown in it's own throws clause, in which case the exception will be propagated further up the stack trace.
If method M2 does neither of the previous two task, you will get a compiler error. Because you haven't given any proper path or way to handle the exception that can be thrown.
Note all the above arguments are true for Checked Exception only. For Unchecked exception, you don't need to handle it yourself, neither you need to declare it in throws clause.
Suggested Read:
Java: checked vs unchecked exception explanation
Unchecked Exception controversies
JLS - The Kinds and Causes of Exceptions
In Java, if a method declares that throws an Exception (other than RuntimeException), callers must handle the exception. They can do this one of two ways: catch it, or declare that they themselves throw it.
You moved the handling of these two exceptions from the SentimentClassifier constructor to its callers.
If the constructor declares any exceptions, the calling code must handle them or declare them. After all, the constructor could throw/propagate these exceptions, and any code that calls it must handle them.
When you catch an exception, it means that you will deal with it on the catch block, and its consequences, so the external code can continue to progress without being warned about the internal exception.
If your exception is thrown, you are forcing by contract to any creator/invoker class to deal with any declared exception that could be produced during the initialization/execution process, as it can be critical for the business logic.
In this case, if the exceptions that can be generated during init are critical, and could stop the class from working properly, they should be thrown, as the creator class TwitterManager could have a disfuncional or partially initialized instance of the SentinelClassifier object, leading to unexpected errors.
In some code I've been reading, I've come across this :
class Someclass
{
public static void main(String[] args) throws IOException
{
//all other code here......
}
}
If main() throws an exception, in this case its an IOException, where is it caught and handled?
EDIT:
Is this considered bad practice? Or is this really common in real world code?
The detailed flowchart of full uncaught exception handling is given here: How uncaught exceptions are handled in Java.
When an uncaught exception occurs, the JVM does the following:
it calls a special private method, dispatchUncaughtException(), on the Thread class in which the exception occurs;
[...which] calls the thread's getUncaughtExceptionHandler() method to find out the appropriate uncaught exception handler to use. Normally, this will actually be the thread's parent ThreadGroup, whose handleException() method by default will print the stack trace.
it then terminates the thread in which the exception occurred.
Therefore you can, if you wish to, create your own custom uncaught exception handler.
It should also be noted that while main is commonly used as a Java application entry point, the method is just like any other methods in that it can also be called from other contexts (e.g. other main methods, or even itself recursively!). In that case, the caller can catch exceptions thrown.
public class SelfCatch {
public static void main(String args[]) throws Exception {
if (args == null) throw new Exception("Hi there!");
try {
main(null);
} catch (Exception e) {
System.out.println("Caught: " + e);
}
System.out.println("Exiting...");
}
}
Output:
Caught: java.lang.Exception: Hi there!
Exiting...
EDIT: Is this considered bad practice?
Or is this really common in real world
code?
It would be in production code, but when rapid prototyping or knocking up test code its often used as its quicker than typing the try {...} catch block. (unless you use a good IDE like Eclipse 3.5 which has an 'Auto wrap in try/catch' feature [auto-detecting any and all exceptions to!] ;-) )
Or your pretty sure it wont be thrown by methods invoked by main().
But even wrapping in a try/catch block will usually result in the same output as if you leave the Exception uncaught, if you simply use e.printStackTrace() ...
At the command line.
EDIT: The entry point is Main. Hence, there is no other method/caller to handle the exception.