JDK-8317229 : try-with-resource can lead to java.lang.IllegalArgumentException: Self-suppression not permitted
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • Submitted: 2023-09-28
  • Updated: 2024-01-31
  • Resolved: 2024-01-31
Related Reports
Relates :  
Relates :  
Description
Consider the following trivial program (also attached):

public class TryWithResource {
    public static void main(final String[] args) throws Exception {
        try (final FooResource foo = new FooResource()) {
            foo.doSomething();
        }
    }


    private static class FooResource implements AutoCloseable {
        private Exception failure;

        private FooResource() {

        }

        private void doSomething() throws Exception {
            if (true) {
                this.failure = new Exception("failed during call to doSomething()");
                throw this.failure;
            }
        }

        @Override
        public void close() throws Exception {
            if (this.failure != null) {
                throw this.failure;
            }
        }

    }
}

The program uses a AutoCloseable in a try-with-resource block. The AutoCloseable implementation in its close() method throws the same instance of an exception which was previously thrown from one of the calls from within the try block.

When this is compiled and run, the program ends up with (an unexpected) "Self-suppression not permitted" exception:

Exception in thread "main" java.lang.IllegalArgumentException: Self-suppression not permitted
    at java.base/java.lang.Throwable.addSuppressed(Throwable.java:1096)
    at TryWithResource.main(TryWithResource.java:3)
Caused by: java.lang.Exception: failed during call to doSomething()
    at TryWithResource$FooResource.doSomething(TryWithResource.java:18)
    at TryWithResource.main(TryWithResource.java:4)

The JLS spec, section 14.20.3 https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-14.20.3 doesn't seem to impose any restrictions on the close() implementation to not throw the same instance of an exception that was previously thrown from within the try block (or from the intialization of the resource).
Comments
For now, closing as will not fix. The feature is worked as designed. There are instances, like the one submitted in the bug, where the policy is unwanted. If in the future the impact of this policy cause more severe problems, the issue an be reconsidered.
31-01-2024

The observed behavior was a conscious design choice of the try-with-resource feature: see for example JDK-6963622. The basic rationale for this choice is that in the common case where separate exceptions are generated for two code blocks, say a block and the block's finally clause, it would be erroneous for an exception to try to suppress itself.
31-01-2024

Joe - feel free to reassign if this is not really your bailiwick
02-10-2023