I run this code:
public class User {
public static void main(String args[]) {
int array[] = new int[10];
int i = 1;
try {
System.out.println("try: " + i++);
System.out.println(array[10]);
System.out.println("try");
} catch (Exception e) {
System.out.println("catch: " + i++);
System.out.println(array[10]);
System.out.println("catch");
} finally {
System.out.println("finally: " + i++);
Object o = null;
o.hashCode();
System.out.println("finally");
}
}
}
Result: try: 1 catch: 2
finally: 3 Exception in thread
"main" java.lang.NullPointerException
at user.main(User.java:17)
in block catch - ArrayIndexOutOfBoundsException, but we loss this Exception, why?
From the JLS
You can read about this in the JLS, Blocks and Statements, section "14.19.2 Execution of try-catch-finally". And I quote,
If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded). The example...
Therefore, the following (which is really condensed from the questioner's code) completes with an NPE, not the ExceptionTest thrown.
class Phinally
{
static class ExceptionTest extends Exception
{ public ExceptionTest(String message) { super(message); } }
public static void main(String[] args) throws ExceptionTest
{
try {
System.out.println("Foo.");
throw new ExceptionTest("throw from try");
} finally {
throw new NullPointerException("throw from finally");
}
}
}
A Sidebar about try with resources/ARM blocks
Difficulties reasoning about this in some common cases specifically with managing resources, and requiring nested try/catch/finally blocks, and nested inside finally blocks, are part of the reason for the "try with resource" feature in project COIN (to be integrated into Java "fairly soon"), about which you can read more about here.
This is one of many good reasons to invest the time in running a static analyzer like PMD, which finds and complains about this type of confusion -- though it might not catch the case in your code, I'm not sure.
Static Checking
Follow up on comment from #stacktrace: I ran the relevant code through PMD and FindBugs, trying both of the following:
finally { throw NullPointerException("Foo"); }
and
finally { Object o = null; System.out.println(o.toString()); }
For the former, PMD noticed and complained about an exception being thrown from a finally clause. FindBugs doesn't complain at all. For the latter, PMD complained about several things but nothing related ("LocalVariableCouldBeFinal", "StringToString", and "UselessOperationOnImmutable"). However, FindBugs noticed and complained about a null dereference. Moral of the story? Run both PMD and FindBugs!
Related
Related on SO: Swallowing exception thrown in catch/finally. Can I avoid such cumbersome try/catch/finally...
You have just stumbled upon an odd feature of Java, that if the finally block doesn't terminate properly, it hides any exceptions that were previously thrown.
This is by design, it is not a mistake.
You last exception doesn't occur inside a try { } catch { } block so there is no catch { } or finally { } processing.
Related
This might be a really dumb question to most of you here, really sorry about that. I am new to java and the book i am reading didn't explain the working of an example in it.
public class CrazyWithZeros
{
public static void main(String[] args)
{
try
{
int answer = divideTheseNumbers(5, 0);
}
catch (Exception e)
{
System.out.println("Tried twice, "
+ "still didn't work!");
}
}
public static int divideTheseNumbers(int a, int b) throws Exception
{
int c;
try
{
c = a / b;
System.out.println("It worked!");
}
catch (Exception e)
{
System.out.println("Didn't work the first time.");
c = a / b;
System.out.println("It worked the second time!");
}
finally
{
System.out.println("Better clean up my mess.");
}
System.out.println("It worked after all.");
return c;
}
}
I can't figure out where the control will go after another exception is generated in catch block in divideTheseNumbers() method ?
Any help will be appreciated !
Output for your program will be
Didn't work the first time.
Better clean up my mess.
Tried twice, still didn't work!
Didn't work the first time. - because of the catch block in divideTheseNumbers
Better clean up my mess. - because of the finally block in divideTheseNumbers
Tried twice, still didn't work! - because of the catch block in the main method.
In general when a exception is thrown from a method and if is not in a try block, it will be thrown to it's calling method.
There are two points to note :
1) Any exception that is not in a try block will be just thrown to
it's calling method(even if it is in a catch block)
2) finally block is always executed.
In your case, you are getting the second exception in catch block, so it will be thrown. But before exiting any method it will also execute finally block(finally block is always executed). That is why Better clean up my mess is also printed.
Some points regarding exception handling:
1. Place your code that may causes exception inside the try{} block.
2. Catch the appropriate exception using the catch block.
3. While catching exception it's better use more specific type exception instead of catching the generic exception like. For example you catch the Exception, in this case you may catch the more specific type exception ArithmeticException.
4. finally block always executed, even though you use return statement in catch or try block.
5. A method either throws or catch an exception. If a method catch an exception then for it is not required to throws the exception.
6. All exception need not to be handled by using catch-block. We can avoid the try-catch block for the unchecked exception like - ArithmeticException,NullPointerException, ArrayIndexOutOfBoundsException. See here for more.
You may also check the tutorial for learning more about exception handling.
Please explain why Exception comes in first program but not in second program.
1) without return statement in read method
class Example
{
public static void read()
{
try
{
int i = 9/0;
}
finally
{
System.out.println("This proogram is giving exception");
}
}
public static void main(String[] fel)
{
read();
}
}
2)with return statement in read method
class Example
{
public static void read()
{
try
{
int i = 9/0;
}
finally
{
System.out.println("This proogram is not giving exception");
return;
}
}
public static void main(String[] fel)
{
read();
}
}
The reason is given in the Java Language Specification rules governing the execution of try/finally blocks. Essentially
if the try block throws an exception E and the finally completes normally then the overall try/finally throws E
if the try block throws E but the finally does not complete normally, then E is ignored and the overall try/finally "completes abruptly" for the reason arising from the finally block
An explicit return is considered abrupt rather than normal completion, so in your example 2 the return inside the finally masks the divide-by-zero exception raised by the try.
Branching statements(return ,goto ) should no be used inside finally because execution of such statement nullifies other instructions which are executed before finally.
The Java Language Specification says : If execution of the try block completes abruptly for any other reason R, then the finally block is executed, and then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
Note - A return statement inside a finally block will cause any exception that might be thrown in the try or catch block to be discarded.
In both instance, the code with throw a java.lang.ArithmeticException, however the return in the finally discards the exception and instead the method exits without forwarding the exception to the caller.
This is one of the reason why in general you should not use a return in a finally-block.
This is described in the Java Language Specification (8), 14.20.2 Execution of try-finally and try-catch-finally:
If execution of the try block completes abruptly because of a throw of
a value V, then there is a choice:
... (some similar but for this case irrelevant rules left out)
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).
You can find the definition of abrupt and normal completion in JLS 14.1 Normal and Abrupt Completion of Statements. But basically a return is considered an abrupt completion.
Is there any functional difference?
Connection c = null;
try {
c = getConnection();
c.doStuff();
} finally {
if (c!=null) c.close();
}
vs
Connection c = null;
c = getConnection();
c.doStuff();
try {
} finally {
if (c!=null) c.close();
}
vs
Connection c = null;
try {
c = getConnection();
} finally {
if (c!=null) c.close();
}
c.doStuff();
I feel that all of them will do the same thing in all cases
Craig already addressed the unhandled exception issue, but I wanted to make it clear. I coded up two examples (the last is just bad because you could be working with a broken connection after an exception has occurred, don't do that). Here is a simple example that throws an ArrayIndexOutOfBoundsException:
class TryCatchFinally {
static int [] array = new int[1];
public static void main(String [] args) throws Exception {
if (args[0].startsWith("1")) {
version1();
} else if (args[0].startsWith("2")) {
version2();
}
}
static int version1() {
int r = 0;
try {
System.out.println("In Try.");
return array[1];
} catch (Exception e) {
System.out.println("In Catch.");
} finally {
System.out.println("In Finally.");
}
System.out.println("In Return.");
return r;
}
static int version2() {
int r = array[1];
try {
System.out.println("In Try.");
} catch (Exception e) {
System.out.println("In Catch.");
} finally {
System.out.println("In Finally.");
}
System.out.println("In Return.");
return r;
}
}
And here is the execution:
(TryCatchFinally)$ javac *.java
(TryCatchFinally)$ java TryCatchFinally 1
In Try.
In Catch.
In Finally.
In Return.
(TryCatchFinally)$ java TryCatchFinally 2
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at TryCatchFinally.version2(TryCatchFinally.java:24)
at TryCatchFinally.main(TryCatchFinally.java:7)
(TryCatchFinally)$
As you can see in the first version an exception handler was registered because the exception occurred within the context of a try block. In the second version there was no registered exception handler and the default exception handler was invoked (meaning an uncaught exception).
An exception that occurs outside of a try-finally block is by definition an unhandled exception. That being the case, you don't have any guarantees about how the operating system or runtime will deal with it. Chances are good that an exception unwind won't be triggered, your code will simply abort (maybe abend describes it better in this discussion--"abnormal end"), and your finally block will never execute.
The point of try-finally is to guarantee that code cleanup occurs, and occurs in the correct context.
You must be thinking that the code in the finally block is always going to execute no matter what, and that it is going to execute after the entire method finishes, therefore it doesn't matter whether the other code is located inside or outside the try-finally construct, but that is not correct.
So if you want any run-time guarantees of correct behavior your first example is the only correct one.
In your first example, you acquire and more importantly use a connection (to a database, one would presume) inside the try block. If an exception occurs within the try block, then the finally block will execute and close your connection.
In your second example, your connection is acquired and used completely outside of the try-catch construct. If an exception occurs using the connection, it is likely that the whole context will just be tossed out, your finally block will not execute, and your connection will not be closed.
In your third example, finally is going to execute after try, but before any code that comes after the finally block. You will generate an exception trying to use the connection, because the connection has already been explicitly closed.
I was going through the following code:
public int returnSomething() {
try {
throw new RuntimeException("foo!");
} finally {
return 0;
}
}
Please explain what this piece of code is doing. My analysis is that we are throwing a runtime exception inside the method, but after that, the "finally" block will definitely execute. Is that correct?
The answer is in the Java Language Specification section 14.20.2. You need to be aware that returning counts as "completing abruptly":
...
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice
[...]
If the finally block completes abruptly for any reason, then the try statement completes abruptly for the same reason.
(All paths have that same final point, with some slightly different wording.)
So the overall result is that 0 is returned and the exception is discarded.
It's rarely a good idea to return from a finally block.
The contents of the finally block always gets executed. The only few reasons I know it won't execute is when you pull the plug or your JVM crashes. SO I reckon this will return 0.
A quick test shows that this returns 0, instead of propagating the RuntimeException.
public class Test {
public static int returnSomething() {
try {
throw new RuntimeException("foo!");
} finally {
return 0;
}
}
public static void main(String[] args) {
int i=returnSomething();
System.out.println(i);
}
}
Today at work, I had to review a code snippet that looks similar to this mock example.
package test;
import java.io.IOException;
import org.apache.log4j.Logger;
public class ExceptionTester {
public static Logger logger = Logger.getLogger(ExceptionTester.class);
public void test() throws IOException {
new IOException();
}
public static void main(String[] args) {
ExceptionTester comparator = new ExceptionTester();
try {
try {
comparator.test();
} finally {
System.out.println("Finally 1");
}
} catch(IOException ex) {
logger.error("Exception happened" ex);
// also close opened resources
}
System.out.println("Exiting out of the program");
}
}
It's printing the following output.I expected an compile error since the inner try did not have a catch block.
Finally 1
Exiting out of the program
I do not understand why IOException is caught by the outer catch block. I would appreciate if anyone can explain this, especially by citing stack unwinding process
A finally block represents a task that has to be done under both normal and abnormal conditions.
Example: You take an interview candidate to lunch. While at lunch, you find out he's wanted by the police for murder. Exception! Lunch is over, the interview is a total loss, but... you still have to pay for lunch.
try {
meetForLunch(interviewCandidate);
}
finally {
lunchBill.pay();
}
Note that paying for lunch hasn't taken care of the exception, you've still got to do something about the murderer at your interview. It's just a loose end that has to be taken care of before processing with damage control.
Most finally blocks are used in that way: A file needs to be closed whether you successfully saved the data or not, a database connection needs to be closed whether the transaction was approved or not, etc.
And the exception continues outward on its merry way, looking for a matching catch block in an enclosing scope.
Note that finally blocks will always run unless the process ends while the try block is still executing.
I think the problem is that your function
public void test() throws IOException {
new IOException();
}
Doesn't actually throw an exception - it just creates a new IOException() object. Changing this to
public void test() throws IOException {
throw new IOException();
}
should fix this.
The code above does not require much of an explanation - not definitely involving call stacks!. What is your confusion?did I miss something?
Here is my explanation
First point
You don't need both a catch and a
finally block. You can have one of
them or both of them with a
try-block, but not none of them.
The code inside the finally clause
will always be executed, even if an
exception is thrown from within the
try or catch block. If your code has
a return statement inside the try or
catch block, the code inside the
finally-block will get executed
before returning from the method.
So in the above code, an exception was never thrown (because you are not using throw in the test() method)
However, finally block got executed as promised by the the language spec and you got the output Finally 1. The next statement in the sequence of execution is the System.out.println("Exiting out of the program"); as the catch block never reached as there are no IOExceptions. So, Exiting out of the program is printed.