What is a suppressed exception?
Asked Answered
F

8

93

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.

Flyman answered 21/10, 2011 at 12:31 Comment(3)
I see no mention of it in the "Java Programming Language Enhancements" description download.oracle.com/javase/7/docs/technotes/guides/language/…Flyman
ARM means Automatic Resource Management, e.g. infoq.com/news/2010/08/arm-blocksPinko
ARM, in this context, is is the old name for try-with-resources. They stopped using ARM and started using try-with-resources sometime before Java 7 shipped. And @danielkullmann is right in what ARM stands forBarozzi
C
58

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.)

Cosmetic answered 21/10, 2011 at 12:34 Comment(4)
Relevant API call: download.oracle.com/javase/7/docs/api/java/lang/…Flyman
@Raedwald: Mostly, yes, I think so.Cosmetic
@JonSkeet @Flyman : I believe this answer fails to consider that suppressed exceptions existed before Java 7 (I'm not talking about ignored exceptions): if a finally block throws an exception when the try block threw an exception as well, the original exception from the try block is lost or "suppressed" (see http://accu.org/index.php/journals/236 for more info). Java 7 just added a convenient method to store the exception from the finally block because the finally is implicitly generated by try-with-resources.Bases
But one point to note is that if we explicitly provide finally block in try-with-resource statement and exception is thrown from it then it takes precedence over exceptions thrown from try or try-with-resource block.Dank
S
81

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.

Sochi answered 21/10, 2011 at 12:41 Comment(7)
So, suppressed exceptions are a consequence of the new feature that means we no longer need to write cumbersome try...finally clauses when opening and close()ing files: #3305905Flyman
@JohnB But we have constructor option of Exception(anotherExcetion e) rit ?Disband
Ok That is called Chained Exceptions.Disband
@KanagaveluSugumar The Exception(Exception cause) constructor is used to wrap a causing exception in another that might be more descriptive. However, in this case we are talking about two distinct exception for which there is no causal relationship. Exception A did not cause Exception B therefore it would not make sense to wrap one in the other. Also, you are assuming the the coder is explicitly throwing the second exception and has access to the first. That would not be the case if both where thrown by library calls.Sochi
@JohnB I think your statement is wrong. "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)" But compiler will choose only finally exception and the try exception will be suppressed.Disband
@KanagaveluSugumar Per documentation: 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 suppressedSochi
Please note that suppressed exceptions is not only useful with try-with-resources, but also with custom code, often in a catch- or a finally-clause, where another exception would otherwise hide the original exception.Wilda
C
58

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.)

Cosmetic answered 21/10, 2011 at 12:34 Comment(4)
Relevant API call: download.oracle.com/javase/7/docs/api/java/lang/…Flyman
@Raedwald: Mostly, yes, I think so.Cosmetic
@JonSkeet @Flyman : I believe this answer fails to consider that suppressed exceptions existed before Java 7 (I'm not talking about ignored exceptions): if a finally block throws an exception when the try block threw an exception as well, the original exception from the try block is lost or "suppressed" (see http://accu.org/index.php/journals/236 for more info). Java 7 just added a convenient method to store the exception from the finally block because the finally is implicitly generated by try-with-resources.Bases
But one point to note is that if we explicitly provide finally block in try-with-resource statement and exception is thrown from it then it takes precedence over exceptions thrown from try or try-with-resource block.Dank
D
27

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.)

Disband answered 20/11, 2014 at 6:42 Comment(0)
M
16

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
Margeret answered 13/5, 2016 at 9:42 Comment(0)
S
10

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.

Septemberseptembrist answered 21/10, 2011 at 13:27 Comment(0)
D
0

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 -

  1. 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.
  2. 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.
  3. 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.

Dank answered 17/10, 2013 at 12:11 Comment(2)
In this case though, the Exception that originates from the try{} block will not automatically be suppressed. The programmer may choose to do so, which you haven't. Only try-with-resources, when need be, shall suppress exceptions automatically. And when he does, it is the exception from your equivalent finally block that will become suppressed.Vernavernacular
@MartinAndersson You are right. Had some confusion when I had written the answer. I hope edited answer provided better insights.Dank
D
0

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

Despair answered 11/6, 2014 at 14:29 Comment(0)
D
-1

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.

Dorene answered 25/3, 2013 at 21:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.