NOTE: This is not an example of how to do something right. This is absolutely the wrong way to handle exception handling in Java.
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /* * Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.bluelotussoftware.example.se; /** * * @author John Yeary <jyeary@bluelotussoftware.com> * @version 1.1 */ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { try { throw new NullPointerException( "NullPointerException 1" ); } catch (NullPointerException e) { throw new NullPointerException( "NullPointerException 2" ); } finally { return ; } } } |
Main2.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /* * Copyright 2011 John Yeary<jyeary@bluelotussoftware.com>. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.bluelotussoftware.example.se; /** * * @author John Yeary<jyeary@bluelotussoftware.com> * @version 1.0 */ public class Main2 { /** * @param args the command line arguments */ public static void main(String[] args) { try { throw new NullPointerException( "NullPointerException 1" ); } finally { return ; } } } |
7 comments :
Based on what we learned from the last JUG...
I believe that both will print out nothing..
The finally at least in JDK 7 will consume the exceptions..
James
To complete the answer.
You would expect the second NPE to be handled after the main method returns however the return statement causes the currently running Thread to need to exit (hence the return causing the private Thread.exit() method to execute immediately rather than closing the JVM down).
The trick is in the finally block. There is a return statement which short circuits the exception processing. The compiler recognizes that there is no way that an exception is thrown so it allows you to do anything you want. The scary part is that run time exceptions are discarded too. I have included the appropriate corner case remarks from the Java Language Standard (JLS) and the actual requirement.
http://java.sun.com/docs/books/jls/third_edition/html/statements.html
§14.20.2 Execution of try-catch-finally
...
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
...
This behavior was described in Eckel's book some 110 years ago:
http://linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ311_014.htm
Konrad Ciborowski
Kraków, Poland
These are great responses. I love it when there are links to other great materials.
Bruce does a great job in "Thinking in Java". He even keeps the material up to date.
This implies that your application could be brought to an abrupt halt without any indication as to why.
Your finally block in your main method has no code in it which should cause it to end abruptly and you have an unhandledException Handler ready in case something untoward happens deeper into your app.
However code in your main finally block causes something like OutOfMemoryError to be thrown in the current Thread and bang, application dies with no indication as to why.
So try {} finally {} is not as safe as one would expect and may have implications for try resources in JDK 7 leading to potential leaks.
The Java Language Specification (JLS) is very specific about the behavior.
Fundamentally, since we are discarding the Exception(s) being thrown at a point where we should handle them, there are no breadcrumbs to tell us what happened.
In this trivial example, the method continues executing and exits normally.
If this were used in the context of a larger application, the implications would be huge in terms of trying to find out why the application crashed.
Post a Comment