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).
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).
- relates to
-
JDK-6963622 Project Coin: Refinements to suppressed exceptions
- Resolved
-
JDK-8287921 FastThrow breaks Throwable.addSuppressed
- New