90

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.

Community
  • 1
  • 1
Raedwald
  • 46,613
  • 43
  • 151
  • 237
  • I see no mention of it in the "Java Programming Language Enhancements" description http://download.oracle.com/javase/7/docs/technotes/guides/language/enhancements.html#javase7 – Raedwald Oct 21 '11 at 12:36
  • 21
    ARM means Automatic Resource Management, e.g. http://www.infoq.com/news/2010/08/arm-blocks – daniel kullmann Oct 21 '11 at 12:47
  • 7
    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 for – Brad Cupit Apr 19 '17 at 14:25

8 Answers8

79

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.

Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
John B
  • 32,493
  • 6
  • 77
  • 98
  • 1
    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: http://stackoverflow.com/questions/3305405/can-i-avoid-such-cumbersome-try-catch-block – Raedwald Oct 21 '11 at 12:54
  • @JohnB But we have constructor option of Exception(anotherExcetion e) rit ? – Kanagavelu Sugumar Nov 20 '14 at 07:01
  • Ok That is called Chained Exceptions. – Kanagavelu Sugumar Nov 20 '14 at 07:24
  • 4
    @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. – John B Nov 20 '14 at 11:46
  • 2
    @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. – Kanagavelu Sugumar Dec 03 '14 at 06:14
  • 1
    @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 suppressed` – John B Dec 03 '14 at 14:51
  • 1
    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. – Puce Jul 01 '19 at 15:42
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.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Relevant API call: http://download.oracle.com/javase/7/docs/api/java/lang/Throwable.html#getSuppressed%28%29 – Raedwald Oct 21 '11 at 12:48
  • @Raedwald: Mostly, yes, I think so. – Jon Skeet Oct 21 '11 at 12:50
  • 6
    @JonSkeet @Raedwald : 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](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. – JBert Nov 22 '11 at 10:36
  • 5
    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. – Aniket Thakur Dec 26 '14 at 14:37
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.)

Kanagavelu Sugumar
  • 18,766
  • 20
  • 94
  • 101
13

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
Adil
  • 4,503
  • 10
  • 46
  • 63
9

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.

Go Dan
  • 15,194
  • 6
  • 41
  • 65
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.

Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289
  • 1
    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. – Martin Andersson Nov 05 '13 at 15:40
  • 1
    @MartinAndersson You are right. Had some confusion when I had written the answer. I hope edited answer provided better insights. – Aniket Thakur Dec 26 '14 at 16:13
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

Jonathan Drapeau
  • 2,610
  • 2
  • 26
  • 32
user2179737
  • 493
  • 3
  • 6
-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.

n00begon
  • 3,503
  • 3
  • 29
  • 42