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

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)

Related

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

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
}
}
}
}

JDK 1.7 onwards, throwing an exception object from catch block does not require a throws clause!!! Why is this so? [duplicate]

This question already has answers here:
Rethrowing an Exception: Why does the method compile without a throws clause?
(5 answers)
Closed 6 years ago.
I came across a weird scenario in java today while coding around. I have a try..catch block in my method which does not have any throws clause and I am able to throw the exception object caught in the catch block. It is an object of the Exception class, hence it is not an unchecked exception. Also, It is not printing the stacktrace if exception arises instead the exception is just getting swallowed.
Below is my code example,
public class ExceptionTest {
public void test() {
try
{
// Some code which may throw exception.
}
catch(Exception ex)
{
// Compiler should ask me to have a *throws Exception* in the signature, when I am throwing an exception object.
throw ex;
}
}
}
However, if I am throwing a new exception object instead of the caught exception object, compiler is asking me to have a throws clause in the method signature.
N.B: I am facing this situation when running in Java 7 or 8.
I am wondering, where is the thrown object going to? Anyone with any idea on this please...
You'll see this if the code in the try block can't throw any checked exception. At that point, the compiler knows that the only kind of exception caught by the catch block has to be an unchecked exception, and so it can therefore be rethrown. Note that if you assigned a different value to ex within the catch block, the compiler would no longer be able to have that assurance. At the moment, ex is effectively final.
If you try to call something that is declared to throw a checked exception within the try block, the code will fail to compile as expected.
For example:
public class ExceptionTest {
public void test() {
try {
foo();
} catch(Exception ex) {
throw ex;
}
}
public void foo() throws java.io.IOException {
}
}
Gives an error of:
ExceptionTest.java:12: error: unreported exception IOException; must be caught or declared to be thrown
throw ex;
^
As for where the exception "goes" - if the code in the try block throws an unchecked exception, it gets propagated as normal. Try this:
public class ExceptionTest {
public static void main(String[] args) {
test();
}
public static void test() {
try {
String x = null;
x.length();
} catch(Exception ex) {
throw ex;
}
}
}
Running that gives the following output, as expected:
Exception in thread "main" java.lang.NullPointerException
at ExceptionTest.test(ExceptionTest.java:10)
at ExceptionTest.main(ExceptionTest.java:4)
JLS 11.2.2 documents what exceptions a statement can throw - your code will only compile if there are no checked exceptions that can be thrown.
please check that you are really throwing an exception in the code. Otherwise the compiler will not care about catching the exception.
public class ExceptionTest {
public void test() {
try
{
throw new Exception("Error");
}
catch(Exception ex)
{
// My Compiler says that I don't catch the exception
throw ex;
}
}
}
Compiler: Error:(14, 13) java: unreported exception java.lang.Exception; must be caught or declared to be thrown

Exception is never thrown in body of corresponding try statement

I have a problem with exception handling in Java, here's my code. I got compiler error when I try to run this line: throw new MojException("Bledne dane");. The error is:
exception MojException is never thrown in body of corresponding try statement
Here is the code:
public class Test {
public static void main(String[] args) throws MojException {
// TODO Auto-generated method stub
for(int i=1;i<args.length;i++){
try{
Integer.parseInt(args[i-1]);
}
catch(MojException e){
throw new MojException("Bledne dane");
}
try{
WierszTrojkataPascala a = new WierszTrojkataPascala(Integer.parseInt(args[0]));
System.out.println(args[i]+" : "+a.wspolczynnik(Integer.parseInt(args[i])));
}
catch(MojException e){
throw new MojException(args[i]+" "+e.getMessage());
}
}
}
}
And here is a code of MojException:
public class MojException extends Exception{
MojException(String s){
super(s);
}
}
Can anyone help me with this?
A catch-block in a try statement needs to catch exactly the exception that the code inside the try {}-block can throw (or a super class of that).
try {
//do something that throws ExceptionA, e.g.
throw new ExceptionA("I am Exception Alpha!");
}
catch(ExceptionA e) {
//do something to handle the exception, e.g.
System.out.println("Message: " + e.getMessage());
}
What you are trying to do is this:
try {
throw new ExceptionB("I am Exception Bravo!");
}
catch(ExceptionA e) {
System.out.println("Message: " + e.getMessage());
}
This will lead to an compiler error, because your java knows that you are trying to catch an exception that will NEVER EVER EVER occur. Thus you would get: exception ExceptionA is never thrown in body of corresponding try statement.
As pointed out in the comments, you cannot catch an exception that's not thrown by the code within your try block. Try changing your code to:
try{
Integer.parseInt(args[i-1]); // this only throws a NumberFormatException
}
catch(NumberFormatException e){
throw new MojException("Bledne dane");
}
Always check the documentation to see what exceptions are thrown by each method. You may also wish to read up on the subject of checked vs unchecked exceptions before that causes you any confusion in the future.
Any class which extends Exception class will be a user defined Checked exception class where as any class which extends RuntimeException will be Unchecked exception class.
as mentioned in User defined exception are checked or unchecked exceptions
So, not throwing the checked exception(be it user-defined or built-in exception) gives compile time error.
Checked exception are the exceptions that are checked at compile time.
Unchecked exception are the exceptions that are not checked at compiled time
Always remember that in case of checked exception you can catch only after throwing the exception(either you throw or any inbuilt method used in your code can throw) ,but in case of unchecked exception You an catch even when you have not thrown that exception.

What is a suppressed exception?

A comment (by user soc) on an answer to a question about tail call optimisation mentioned that Java 7 has a new feature called "suppressed exceptions", because of "the addition of ARM" (support for ARM CPUs?).
What is a "suppressed exception" in this context? In other contexts a "suppressed exception" would be an exception that was caught and then ignored (rarely a good idea); this is clearly something different.
To clarify the quote in Jon's answer, only one exception can be thrown by a method (per execution) but it is possible, in the case of a try-with-resources, for multiple exceptions to be thrown. For instance one might be thrown in the block and another might be thrown from the implicit finally provided by the try-with-resources.
The compiler has to determine which of these to "really" throw. It chooses to throw the exception raised in the explicit code (the code in the try block) rather than the one thrown by the implicit code (the finally block). Therefore the exception(s) thrown in the implicit block are suppressed (ignored). This only occurs in the case of multiple exceptions.
I believe the commenter is referring to is an exception which is semi-ignored when it's thrown within the implicit finally block of a try-with-resources block, in the context of an existing exception being thrown from the try block:
An exception can be thrown from the block of code associated with the try-with-resources statement. In the example writeToFileZipFileContents, an exception can be thrown from the try block, and up to two exceptions can be thrown from the try-with-resources statement when it tries to close the ZipFile and BufferedWriter objects. If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed, and the exception thrown by the block is the one that is thrown by the writeToFileZipFileContents method. You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.
(That's quoting a section called "Suppressed Exceptions" from the linked page.)
Before Java7; There are exceptions thrown in the code but were ignored somehow.
e.g.)
public class SuppressedExceptions {
public static void main(String[] args) throws Exception {
try {
callTryFinallyBlock();
} catch (Exception e) {
e.printStackTrace(); **//Only Finally Exception is Caught**
}
}
private static void callTryFinallyBlock() throws Exception {
try
{
throw new TryException(); **//This is lost**
}
finally
{
FinallyException fEx = new FinallyException();
throw fEx;
}
}
}
class TryException extends Exception {
}
class FinallyException extends Exception {
}
A new constructor and two new methods were added to the Throwable class in JDK 7.
These are as below:
Throwable.getSupressed(); // Returns Throwable[]
Throwable.addSupressed(aThrowable);
with this new approach, we can handle those suppressed exception as well.
public class SuppressedExceptions {
public static void main(String[] args) throws Exception {
try {
callTryFinallyBlock();
} catch (Exception e) {
e.printStackTrace();
for(Throwable t: e.getSuppressed())
{
t.printStackTrace();
}
}
}
private static void callTryFinallyBlock() throws Exception {
Throwable t = null;
try
{
throw new TryException();
}
catch (Exception e) {
t = e;
}
finally
{
FinallyException fEx = new FinallyException();
if(t != null)fEx.addSuppressed(t);
throw fEx;
}
}
}
class TryException extends Exception {
}
class FinallyException extends Exception {
}
In Java7 try-with-resources; the exception at AutoCloseable::close()
is added as suppressed exception by default along with try exception.
Also aware that this is different from chained exceptions (were introduced with JDK 1.4 and were intended to make it possible to easily track causal relationships between exceptions.)
Concedering the code below:
public class MultipleExceptionsExample {
static class IOManip implements Closeable{
#Override
public void close() {
throw new RuntimeException("from IOManip.close");
}
}
public static void main(String[] args) {
try(IOManip ioManip = new IOManip()){
throw new RuntimeException("from try!");
}catch(Exception e){
throw new RuntimeException("from catch!");
}finally{
throw new RuntimeException("from finally!");
}
}
}
With all lines you will get: java.lang.RuntimeException: from finally!
Removing finally block you will get: java.lang.RuntimeException: from catch!
Removing catch block you will get:
Exception in thread "main" java.lang.RuntimeException: from try!
Suppressed: java.lang.RuntimeException: from IOManip.close
Suppressed exceptions are additional exceptions that occur within a try-with-resources statement (introduced in Java 7) when AutoCloseable resources are closed. Because multiple exceptions may occur while closing AutoCloseable resources, additional exceptions are attached to a primary exception as suppressed exceptions.
Looking at the bytecode of a piece of try-with-resources sample code, standard JVM exception handlers are used to accommodate the try-with-resources semantics.
You can suppress Exceptions in Java 6 as well (a little trickery involved),
I created a utility that transparently handles suppressing exception in Java 1.6 and Java 1.7. You can find the implementation here
All you need is to call:
public static <T extends Throwable> T suppress(final T t, final Throwable suppressed)
to supress a exception, and
public static Throwable [] getSuppressed(final Throwable t) {
to get the suppressed exceptions of a Exception, in case anybody still uses Java 1.6
ARM - Automatic Resource Management(Introduced since Java 7)
Take a very simple example
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Now if readLine() function throws Exception and then even close() function [in finally block] throws exception then the later is given more priority and is thrown back to the calling function. In this case the Exception thrown by the readLine() method is ignored/suppressed. You can chain the causing exception in your exception and rethrow your exception from finally block.
Since java 7 functionality has been provided to retrieve suppressed Exceptions. You can call public final java.lang.Throwable[] getSuppressed() function on the catched throwable object to view the suppressed Exceptions.
For Eg.
static String readFirstLineFromFileWithFinallyBlock(String path)
throws Exception {
try (BufferedReader br = new BufferedReader(new FileReader(path));) {
return br.readLine();
}
}
Now if br.readLine(); line throws Exception1 and then lets say Exception2 is thrown while closing the resource [Imagine this happening in an implicit finally block that try-with-resource statement creates] then Exception1 suppresses Exception2.
Few points to note here -
If try-with-resource block throws exception i.e while resource instantiation then try block will not execute and the same exception will be thrown.
If instantiation of resource is successful, try block throws an exception and exception is thrown while closing the resource then the exception thrown while closing resource is suppressed by the exception thrown from try block.
If you provide explicit finally block and exception is thrown from that block it will suppress all other exception. (This explicit finally block executes after resources are closed)
I have compiled most of the possible scenarios with code snippets and output in following post.
Suppressed exceptions in java 7
Hope that helps.
I think this has to do with the "chained exception facility". It will affect how an exception is handled by this facility as the stack trace evolves. Over time exceptions that are part of a group of chained exception can be suppressed. Look at the Throwable documentation for more details.

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