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();
}
Related
"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.
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.
I have a class Game with a constructor with the following signature:
public Game(String[] boardState) throws InvalidStringsInputException, WrongNumberOfMarksException
And there is a method in junit4 testcase:
public static Game newGameFromStringsSuccessful(String[] input) //it is the line 9
{
try
{
return new Game(input);
}
catch (WrongNumberOfMarksException exception)
{
fail("Caught exception where it shouldn't be");
}
catch (InvalidStringsInputException exception)
{
fail("Caught exception where it shouldn't be");
}
}
I am using eclipse and it shows me an error:
This method must return a result of type Game line 9 Java Problem
If I insert return null in the ends of both catch blocks, the error disappears, but my question doesn't: why does java want it even after fail() method is called?
why does java want it even after fail() method is called?
Because the compiler doesn't know that fail can't return normally. There's no way of expressing that within Java. The end of the fail message call is still reachable - so the end of the method is also reachable.
Suppose there was a bug in the fail method, so you ended up reaching the end of the method - what would you expect to happen?
The simplest fix for this is to throw some runtime exception at the end of the method, e.g. AssertionError:
throw new AssertionError("fail must have returned normally!");
It's basically an exception to say "The world is crazy, I don't want to live here any more" - which also keeps the compiler happy, as the closing brace of the method is no longer reachable.
Another alternative - not available here, as you don't control the fail method - would be to declare the fail method to return some kind of runtime exception, at which point your catch blocks could look like this:
catch (InvalidStringsInputException exception)
{
throw fail("Caught exception where it shouldn't be");
}
Of course the implementation of fail would still be to throw an exception rather than return it, but it means the compiler knows that that catch block is definitely not going to complete normally.
Jon's answer below explains why the compiler is complaining. However, I suggest that the correct way to avoid this is to not have the try/catch in you test. Just let the exception propagate up the call stack and out of your test. JUnit will catch it and fail the test while providing the entire stack trace of where the exception was thrown.
Or if you prefer not to have to propagate the throws clause, wrap the exception in a RuntimeException and then throw that. Again, this will provide the stack trace to allow for better diagnosis.
Suppose i have a method that may fail with a checked exception (checked because it is recoverable, according to Sun's recommendations).
This method fails and it triggers a recovery strategy.
But both the initial method and the recovery strategy failed.
In some cases i may want to have both stacktraces so that i know why both the initial and recovery strategies failed, and not only the last one.
What can i do?
Should i create a CompositeException type or something like that? Is it a good practice?
Java 7 has introduced the concept of a suppressed exception. For instance, the try-with-resources statement is specified by:
Resources are closed in the reverse order from that in which they were initialized. A resource is closed only if it initialized to a non-null value. An exception from the closing of one resource does not prevent the closing of other resources. Such an exception is suppressed if an exception was thrown previously by an initializer, the try block, or the closing of a resource.
and
If the initialization of the resource completes normally, and the try block completes abruptly because of a throw of a value V, then:
If the automatic closing of the resource completes abruptly because of a throw of a value V2, then the try-with-resources statement completes abruptly because of a throw of value V with V2 added to the suppressed exception list of V.
This uses java.lang.Throwable.addSuppressedException, whose javadoc reads:
Appends the specified exception to the exceptions that were suppressed in order to deliver this exception. This method is thread-safe and typically called (automatically and implicitly) by the try-with-resources statement.
The suppression behavior is enabled unless disabled via a constructor. When suppression is disabled, this method does nothing other than to validate its argument.
Note that when one exception causes another exception, the first exception is usually caught and then the second exception is thrown in response. In other words, there is a causal connection between the two exceptions. In contrast, there are situations where two independent exceptions can be thrown in sibling code blocks, in particular in the try block of a try-with-resources statement and the compiler-generated finally block which closes the resource. In these situations, only one of the thrown exceptions can be propagated. In the try-with-resources statement, when there are two such exceptions, the exception originating from the try block is propagated and the exception from the finally block is added to the list of exceptions suppressed by the exception from the try block. As an exception unwinds the stack, it can accumulate multiple suppressed exceptions.
An exception may have suppressed exceptions while also being caused by another exception. Whether or not an exception has a cause is semantically known at the time of its creation, unlike whether or not an exception will suppress other exceptions which is typically only determined after an exception is thrown.
Note that programmer written code is also able to take advantage of calling this method in situations where there are multiple sibling exceptions and only one can be propagated.
That last paragraph seems to apply to your situation. So you could do:
public static void main(String[] args) throws Exception {
try {
throw new RuntimeException("Not now!");
} catch (Exception e) {
try {
tryAgain();
} catch (Exception e2) {
e.addSuppressed(e2);
throw e;
}
}
}
Then, the stack trace will contain both exceptions:
Exception in thread "main" java.lang.RuntimeException: Not now!
at tools.Test.main(Test.java:12)
Suppressed: java.lang.RuntimeException: I'm on holiday.
at tools.Test.tryAgain(Test.java:7)
at tools.Test.main(Test.java:15)
but only the primary exception can be caught by the caller.
I would consider an exception for when the initial method fails and another for when the recovery strategy fails.
You may want to do something like try the recovery strategy multiple times before throwing a exception that recovery failed (e.g. retry and fail when timeout occurs).
It seems like keeping the initial method and recovery strategy exceptions separated makes sense, as they represent two different scenarios.
Unfortunately, a Java Exception only has one cause, so a CompositeException may be your best option. However, you can override the printStackTrace methods to print the stack traces of your composite exceptions:
public class CompositeException extends Exception {
private final List<Throwable> causes = new ArrayList<Throwable>();
public CompositeException(Throwable... causes) {
this.causes.addAll(Arrays.asList(causes));
}
// Other constructors you want
#Override
public void printStackTrace() {
if (causes.isEmpty()) {
super.printStackTrace();
return;
}
for (Throwable cause : causes) {
cause.printStackTrace();
}
}
#Override
public void printStackTrace(PrintStream s) {
if (causes.isEmpty()) {
super.printStackTrace(s);
return;
}
for (Throwable cause : causes) {
cause.printStackTrace(s);
}
}
#Override
public void printStackTrace(PrintWriter s) {
if (causes.isEmpty()) {
super.printStackTrace(s);
return;
}
for (Throwable cause : causes) {
cause.printStackTrace(s);
}
}
}
This is about all you can do to have multiple cause exceptions in one exception. To use it:
CompositeException ce = new CompositeException(ex1, ex2, ex3);
Then ce.printStackTrace() will print all 3 exceptions' stack traces.
What do you exactly mean with "I may want to have both stacktraces"? What I use to do is log both, since they're "things that should not happen". It allows you to check the log and trace what is wrong. If you do "CompositeException" you'll soon explode on combinatory issues: what if "CompositeExceptionHandler" also fails?
I would...
Trace the first exception and act if you can. Otherwise and raise a custom exception.
Catch the second one and act accordingly.
That way you improve coupling. You handle both levels independently
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.