RFE: make AutoCloseable generic in its exception type

Rob Spoor openjdk at icemanx.nl
Wed Oct 8 16:33:03 UTC 2025


I have two scenarios where I'd like to have this.

The first scenario is existing APIs where classes haven't been changed 
to implement AutoCloseable yet. Think of JMS several years ago, or even 
ExecutorService before Java 19. These cannot be used in 
try-with-resources without creating an interface with a different 
exception (JMSException, RuntimeException) or requiring to deal with 
Exception.

     try (AutoCloseable _ = executor::shutdown) {
     } // have to deal with Exception


The second scenario comes from one of my projects. I have a class where 
the close() method cannot be made public. To be able to use it in 
try-with-resources I had to create a custom wrapper class.

     Transaction transaction = Transaction.create(timeout, description);
     // custom class instead of AutoCloseable<MyException> _ = 
transaction::close
     try (var _ = new TransactionCloseable(transaction)) {
     }


Regarding the comparison with try-finally, I've encountered the first 
pre-condition often enough, like JMS. I don't think the second 
pre-condition is required, because we can use lambdas instead of method 
references.

Regardoing a subinterface, that could definitely work. It would also get 
rid of the possible clash with the "of" method. I can of course create 
it myself, but then I'll have to create a library for just this single 
interface, or duplicate it in all projects where it would be needed 
(I've already identified a handful or so), so it would be very nice if 
it could be added to the JDK.

Kind regards,

Rob


On 07/10/2025 23:57, Chen Liang wrote:
> Hi Rob,
> Can you share an actual piece of code that would benefit from such a lambda migration?
> I have checked the library code of java.base module; the try-with-resources and finally are mostly used for I/O and security cleanups, none of which would significantly benefit from this improvement.
> In particular, I noted this form would only be more useful than finally with these preconditions:
> 
>    1.
> The cleanup action must be throwing some exception
>    2.
> The cleanup action doesn't make use of local variables
> 
> Which IMO makes this usage much more niche.
> Finally, for your proposed solution, I think we can accomplish that with a subinterface of AutoCloseable that has this type parameter - this does not require existing implementors to update, yet offers the same benefits.
> 
> Regards,
> Chen Liang
> 
> Confidential – Oracle Internal
> ________________________________
> From: core-libs-dev <core-libs-dev-retn at openjdk.org> on behalf of Rob Spoor <openjdk at icemanx.nl>
> Sent: Tuesday, October 7, 2025 2:43 PM
> To: core-libs-dev at openjdk.java.net <core-libs-dev at openjdk.java.net>
> Subject: RFE: make AutoCloseable generic in its exception type
> 
> Hi all,
> 
> AutoCloseable, as added in Java 7 and unchanged ever since, declares to
> throw Exception from its close() method. That means that anytime someone
> needs to have an AutoCloseable that throws a different exception, they
> must create an interface that extends AutoCloseable and override close()
> only to throw a different (or no) exception. That can become quite
> annoying if you have to do it often. But without such interfaces, we
> cannot use lambdas or method references in try-with-resources without
> having to deal with Exception:
> 
>       try (AutoCloseable _ = this::cleanup) {
>       } // need to catch or re-throw Exception
> 
> 
> I think that making AutoCloseable generic in its exception type is a
> change that's quite simple, yet makes life easier for developers. The
> interface would become this:
> 
>       public interface AutoCloseable<X extends Exception> {
>           /**
>            * <existing javadoc minus throws
>            *
>            * @throws X if this resource cannot be closed
>            */
>           void close() throws X;
>       }
> 
> In its raw form, the interface is exactly what we already have: close()
> throws Exception. Therefore, any use of AutoCloseable that doesn't fill
> in the generic type (including extending interfaces) will work as they
> do now. They can still override close() and change the thrown exception
> type. Interfaces that extend AutoCloseable can fill in the generic type,
> and if the close() method doesn't add additional documentation it can be
> removed completely. Interfaces like Closeable will only have to change
> the extends clause:
> 
>       public interface Closeable extends AutoCloseable<IOException> {
>           // keep close for its documentation
>       }
> 
> That doesn't add much value yet, but we can now use it in
> try-with-resources without having to deal with Exception:
> 
>       try (AutoCloseable<RuntimeException> c = this::cleanup) {
>       } // no need to catch or re-throw RuntimeException
> 
> 
> There is one other possible change that can make it even easier, and
> that is adding a factory method like Gatherer.Integrator.of:
> 
>       public interface AutoCloseable<X extends Exception> {
>           // documentation omitted
>           void close() throws X;
> 
>           // documentation omitted
>           static <X extends Exception> AutoCloseable<X>
> of(AutoCloseable<X> closeable) {
>               return closeable;
>           }
>       }
> 
> The try-with-resources can now become even simpler:
> 
>      try (var _ = AutoCloseable.of(this::cleanup)) {
>      }
> 
> 
> There is one possible issue with this "of" method, and that is possible
> incompatibilities with existing implementing classes or extending
> interfaces that already have an "of(AutoCloseable)" method with a
> different return type, or that are not static. I think the chances of
> that are not great, but it still is something to consider.
> 
> 
> Any thoughts?
> 
> 



More information about the core-libs-dev mailing list