Java - detect whether there is an exception in progress during `finally` block - java

I am considering this from the Java Language Specification:
If the catch block completes abruptly for 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).
I have a block as follows:
try {
.. do stuff that might throw RuntimeException ...
} finally {
try {
.. finally block stuff that might throw RuntimeException ...
} catch {
// what to do here???
}
}
Ideally, I would want any RuntimeException thrown in the finally block to escape, only if it would not cause a RuntimeException thrown in the main try block to be discarded.
Is there any way in Java for me to know whether the block that is associated with a finally block completed normally or not?
I'm guessing I could just set a boolean as the very last statement of the main try block (e.g., completedNormally = true. Is that the best way, or is there something better / more standard?

I believe the key is to not lose the original cause if any.
If we look at how try-with-resources behave:
private static class SomeAutoCloseableThing implements AutoCloseable {
#Override
public void close() {
throw new IllegalStateException("closing failed");
}
}
public static void main(String[] args) {
try (SomeAutoCloseableThing thing = new SomeAutoCloseableThing()) {
throw new IllegalStateException("running failed");
}
}
We end up with:
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:16)
Suppressed: java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:17)
This stack trace is great as we see both exceptions, i.e. we don't lose the running failed one.
Implementing this without try-with-resources, the wrong way:
public static void main(String[] args) {
SomeAutoCloseableThing thing = new SomeAutoCloseableThing();
try {
throw new IllegalStateException("running failed");
} finally {
thing.close();
}
}
We end up with:
Exception in thread "main" java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:19)
We don't know that running failed occurred too as we broke the control flow, that's quite bad if you need to debug such a case.
Implementing this without try-with-resources, the right way (in my opinion), is to "log and forget" the exception that occurred in the finally block:
public static void main(String[] args) {
SomeAutoCloseableThing thing = new SomeAutoCloseableThing();
try {
throw new IllegalStateException("running failed");
} finally {
try {
thing.close();
} catch (Exception e) {
LoggerFactory.getLogger(Main.class).error("An error occurred while closing SomeAutoCloseableThing", e);
}
}
}
We end up with:
17:10:20.030 [main] ERROR Main - An error occurred while closing SomeAutoCloseableThing
java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:10) ~[classes/:?]
at Main.main(Main.java:21) [classes/:?]
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:18)
Not as good as the try-with-resources approach, but at least we know what actually happened, nothing got lost.

I assume your finally block is doing cleanup. A good way to accomplish such cleanup is to create a class that implements AutoCloseable, so your code can place it in a try-with-resources statement:
class DoStuff
implements AutoCloseable {
public void doStuffThatMightThrowException() {
// ...
}
#Override
public void close() {
// do cleanup
}
}
(Notice that it does not need to be a public class. In fact, it probably shouldn’t be.)
The code in your example would then look like this:
try (DoStuff d = new DoStuff()) {
d.doStuffThatMightThrowException();
}
As for what happens if an exception is thrown during the cleanup: it becomes a suppressed exception. It won’t show up in a stack trace, but you can access it if you really want to (which you probably won’t).

I don't think there is an idiomatic solution to this problem, partly because you normally use finally to clean-up resources disregarding completely if the code that allocated the resource terminated normally or not.
For example you finally close a connection, but the transaction will be rolled back in the catch block or committed as a last statement of the code block wrapped in the try.
Concerning an throwable thrown inside the finally block, you should decide which exception is most important to pass on to the caller. You can ultimately create your own exception which holds reference to both exceptions, in that case you need to declare a variable initialized outside the try and set inside the catch.
For example, in the following code you either complete normally or throw an exception, while having tried a recovery (rolling back a transaction) and tried a clean-up in finally.
Either can fail and you wrap what you think is the most important data in the exception you finally throw.
private void foo() throws SQLException {
Throwable firstCause = null;
try {
conn.prepareStatement("...");
// ...
conn.commit();
} catch (SQLException e) {
firstCause = e;
conn.rollback();
throw e;
} finally {
try {
conn.close();
} catch (Exception e) {
throw new RuntimeException(firstCause);
// or
// throw new RuntimeException(e);
// or
// throw new MyException(e,firstCause);
}
}
}

You could capture the original exception and re-throw it from within finally block.
Code below does just that and the exception thrown out of the method below will have the stacktrace and the cause dictated by the outer RuntimeException.
private void testException() {
RuntimeException originalFailure = null;
try {
throw new RuntimeException("Main exception");
} catch (RuntimeException e) {
originalFailure = e;
} finally {
try {
throw new RuntimeException("Final exception");
} catch (RuntimeException e) {
if (originalFailure != null) {
throw originalFailure;
} else {
throw e; //OR do nothing
}
}
}
}

Related

Can exception masking be completely prevented with try-with-resources statement

I'm aware that try-with-resources statement was introduced to cure (or) prevent exception masking.
Consider the following code:
class TestExceptionSuppressing {
public static void main(String[] args) {
try {
testMethod();
} catch (Exception e) {
System.out.println(e.getMessage());
for (Throwable t : e.getSuppressed()) {
System.err.println("Suppressed Exceptions List: " + t);
}
}
}
static void testMethod() {
try (InnerClass inner = new InnerClass()) {
throw new IOException("Exception thrown within try block");
} catch (Exception e) {
throw new RuntimeException(
"Exception thrown within catch block.Hence exception thrown within try block will be lost (or) masked");
}
}
static class InnerClass implements AutoCloseable {
#Override
public void close() throws Exception {
throw new Exception("Exception thrown in close method will be tacked on to existing exceptions");
}
}
}
Output: Exception thrown within catch block.Hence exception thrown within try block will be lost (or) masked
Apparently, exception thrown in catch block of testMethod() has masked both the io exception thrown in try block and also the exception suppressed and added to this io exception(thrown in close method )
This code example might prove that try-with-resources may not completely prevent exception masking.
I'm aware things are mixed up in here and might be confused but is a possible case to happen. My question is, is there a way to prevent this scenario i.e. exception masking to still happen even when using try-with-resources statement?
You can keep the original exception if you use RuntimeException(String, Throwable)
Constructs a new runtime exception with the specified detail message and cause.
throw new RuntimeException(
"Exception thrown within catch block won't be lost (or) masked", e);
If you want to add the suppressed try and resources exception, you need to use the addSuppressed(Throwable) method, in your case:
RuntimeException runtimeException = new RuntimeException(
"Exception thrown within try block won't be lost (or) masked", e);
runtimeException.addSuppressed(e.getSuppressed()[0]);
More info in Suppressed Exceptions and Try With Resources
However, just because the CloseException is supressed in this scenario, it doesn't mean this suppressed exception has be ignored. To address this concept of suppressed exceptions, two new methods and a constructor have been added to the java.lang.Throwable class in Java 7.
public final void addSuppressed(Throwable exception)

Are Suppressed Exceptions only encountered in try-with resources codes? [duplicate]

This question already has answers here:
Multiple returns: Which one sets the final return value?
(7 answers)
Closed 4 years ago.
I am reviewing for OCP and I stumbled upon this scenario with Exceptions.
Typically, we encounter Suppressed Exceptions in try-with-resource. if the try block and close() method both throws an Exception, only the one in try block will be handled. The exception thrown in close() will be suppressed.
I am experimenting other ways to encounter suppressed exceptions. Running methodTwo() will just throw NullPointerException. It will be catched but it is not suppressed. What happened to IllegalArgumentException?
public class Main {
public static void main(String[] args) {
try {
methodTwo();
} catch (Exception e) {
e.printStackTrace();
for(Throwable t : e.getSuppressed()) {
System.out.println(t.getMessage());
}
}
}
static void methodTwo() {
try {
throw new IllegalArgumentException("Illegal Argument");
} finally {
throw new NullPointerException("Null Pointer");
}
}
}
as mentioned by comments, finally always executed if any exception or return happen. it is because of assurance of free resource like files and etc. if you don't return or throw new exception in finally, it return exception or value that set before.
you can change value that return in finally block too for example:
class A
{
public int value; // it is not good but only for test
}
public class Tester
{
public static void main(String[] args) {
System.out.println(method1().value); // print 10
}
private static A method1() {
A a = new A();
try
{
a.value = 5;
return a;
} finally
{
a.value = 10;
}
}
}
you can throw exception instead of throwing new value too and return value or last exception discarded. (but all of this is not good in programming design)
when you working with files, because there is nothing like destructor in java like c++ (although there is finally but it is different) you must using try finally (or for new way, use try-with-resource) to free resource obtained from system.
As explained here by #polygenelubricants
A try statement with a finally block is executed by first executing the try block. Then there is a choice:
If execution of the try block completes normally, [...]
If execution of the try block completes abruptly because of a throw of a value V, [...]
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, [...]
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
For more detail , go to oracle documentation

Java unhandled exception disappears

Suppose there is a class such that:
public class Magic {
public static void main(String[] args){
boolean[] val = new boolean[0];
paradox(val);
}
private static boolean paradox(boolean[] arg) {
Container container = null;
try {
container = Container.getContainer(arg[0]);
return container.value;
} catch (UnsupportedOperationException e) {
e.printStackTrace();
return false;
} finally {
try {
container.sayHi();
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}
}
}
private static class Container{
private boolean value;
private Container(boolean value){
this.value = value;
}
private static Container getContainer(boolean value) throws UnsupportedOperationException{
return new Container(value);
}
private void sayHi(){
System.out.println("Hi!");
}
}
}
If this code is executed, there is a null pointer thrown on line with
container.sayHi();
container should, in fact, be null. Before the assignment can complete there is an ArrayIndexOutOfBoundException thrown when we call getContainer(). However, what happens to the ArrayIndexOutOfBoundException? Why do we go into finally{} after an unhandled exception?
edit: poor phrasing. question is why we go directly into finally{}. And what happens to ArrayIndexOutOfBoundException
Why do we go into finally{} after an unhandled exception?
We always go to finally after a block exits (successfully, after an exception handler, or after an unhandled exception). That's exactly what finally is for: a place to put code that will be run no matter what.
However, what happens to the ArrayIndexOutOfBoundException?
If you encounter a second exception in an exception handler or a finally block, then that second exception will be propagated and the original exception will be hidden.
If you want to preserve the original exception, you can manually attach it to the new exception via Throwable#addSuppressed (or the other way around, re-throw the original exception and attach the new one as suppressed).
There is a simple rule in Java: finally is always called.1
So what happens is this:
container = Container.getContainer(arg[0]);
This throws an ArrayIndexOutOfBoundException, which is uncaught. Before the exception bubbles, finally is called.
container.sayHi();
container == null so a NullPointerException is thrown, this shadows the original exception. As per the JLS §14.20.2
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice
... then
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).
emphasis mine
1: except when System.exit is called or some other rare cirumstances.
Another surprise you may get when doing control flow operations inside finally block :
public static void main(String[] args) {
System.out.println(badFunction());
}
private static String badFunction() {
try {
throw new RuntimeException("Catch it!");
} finally {
return "Exception disappears";
}
}

java exception handling and continuation

I have a Java Program where I get data from a different source. some times while reading I see Exception and the program is exiting.
Mine is in a program that runs every 10minutes.
Public static void main(Strings[] args)
{
...readsource();
}
Private static void readsource() throws IOException
{
...
}
Issue:
I am able to get/See the Exception. But I want the program to continue
To that what is the best logic? I dont see try-catch-finally also is not addressing ..I want the program to continue even after seing the exception (I mean the next iteration should continue). This looks to be a Basic issue not sure how to address this...
Then you need to catch the exception, which you are currently not doing.
try {
readsource();
} catch (IOException e) {
// do something, never catch an exception and not do anything
}
//continue.
Note that exceptions usually indicate something is wrong. Unless you are going to do something about the exception, it might be better to fix the condition causing the exception....
You have to provide an error handler in your method, i.e. surround the call to readsource() with a try-catch block.
public static void main(Strings[] args)
{
try{
...readsource();
}
catch(IOException ioe){
//handle the error here,e.g don't do anything or simply log it
}
}
If you don't rethrow the exception in the catch block, execution will fall off the end of the catch block and continue as if there was no exception.
If you mean you'd like to recall the method wether an Exception was thrown or not just place this in a while loop i.e:
Public static void main(Strings[] args)
{
boolean run=true;
while(run) {
try {
System.out.print("Hello,");
readsource();
throw new IOException();
if(1==2)run=false;//stop the loop for whatever condition
} catch(IOException ioe) {
ioe.printStackTrace();
}
System.out.println(" world!");
}
}
}
Private static void readsource() throws IOException
{
...
}

Why try/catch around throwable?

In trying to refactor some I code I attempted to throw the exception in the catch clause like so -
try {
....
}
catch(Exception exception){
.....
throw exception
}
However when I attempted to throw the exception on line "throw exception" the compiler complained with a message that I needed to surround my throw clause in a new try/catch like so -
try
{
....
}
catch (Exception exception)
{
.....
try
{
throw exception
}
catch (Exception e2)
{
...
}
}
Why does the compiler require this and what use does it provide ?
Thanks
The exception java.lang.Exception is a checked exception. This means that it must either be declared in the throws clause of the enclosing method or caught and handled withing the method body.
However, what you are doing in your "fixed" version is to catch the exception, rethrow it and then immediately catch it again. That doesn't make much sense.
Without seeing the real code, it is not clear what the real solution should be, but I expect that the problem is in the original try { ... } catch handler:
If possible, you should catch a more specific exception at that point, so that when you rethrow it, it is covered by the method's existing throws list.
Alternatively, you could wrap the exception in an unchecked exception and throw that instead.
As a last resort, you could change the signature of the method to include Exception in the throws list. But that's a really bad idea, because it just pushes the problem off to the caller ... and leaves the developer / reader in the position of not knowing what exceptions to expect.
In Java, there is a distinction between checked and unchecked exceptions. An unchecked exception can essentially be thrown at any place in code and, if it's not caught somewhere, it will propagate up to the entry point of your application and then stop the process (usually with an error message and stack trace). A checked exception is different: The compiler won't let you just let it propagate, you need to either surround any code which might throw a checked exception with try-catch blocks (and "throw exception" is the simplest case if exception is an instance of a checked exception class) or you must mark the method which contains the call to code that might throw a checked exception with a "throws" declaration. If the desired behaviour is to throw an unchecked exception, then you'll need to wrap the exception in a RuntimeException. If the desired behaviour is to keep the exception checked, then you'll need to add a throws declaration to your current method.
In your original code, nothing catches the thrown exception. I would imagine you either have to specify that your function throws an exception or have another try/catch block as the compiler suggests to catch it.
Instead of
public void yourFunction(){
try {
....
}
catch(Exception exception){
.....
throw exception
}
}
try
public void yourFunction() throws Exception{
try {
....
}
catch(Exception exception){
.....
throw exception
}
}
My guess is that your trying to throw an exception sub class that isn't declared by the method as an exception type it can throw.
The following example works
package test.example;
public class ExceptionTest {
public static void main(String[] args) throws Exception{
try {
int value = 1/0;
} catch (Exception e) {
System.out.println("woops the world is going to end");
throw e;
}
}
}
However this example will give an error.
package test.example;
public class ExceptionTest {
public static void main(String[] args) throws RuntimeException{
try {
int value = 1/0;
} catch (Exception e) {
System.out.println("woops the world is going to end");
throw e;
}
}
}
Note in the second example I'm simply catching Exception not RuntimeException, it won't compile as I throw Exception which is an undeclared throws, even though I do declare RuntimeException.
Yes the exception is a RuntimeException but the compiler doesn't know that.
Just thought of a third working example to show you. This one also works because your throwing the same type as you declare. (note the only change is the catch block)
package test.example;
public class ExceptionTest {
public static void main(String[] args) throws RuntimeException{
try {
int value = 1/0;
} catch (RuntimeException e) {
System.out.println("woops the world is going to end");
throw e;
}
}
}
You need to understand the differences between all three of these answers

Categories

Resources