Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to close an AutoCloseable

What is the most reliable pattern to follow when closing an OutputStream, ServerSocket, or other object that implements the AutoCloseable interface?

Should I use try-catch-finally? Or a shutdown hook.

like image 304
Raedwald Avatar asked May 13 '19 12:05

Raedwald


1 Answers

The correct way to use an AutoCloseable instance is with a try-with-resources block, so the resource is reliably closed even if an exception is thrown.

Like this:

    try (OutputStream stream = new ...) {
       ... // use the resource
    } catch (IOException e) {
        ... // exception handling code
    }

You can also control multiple resources using one block (rather than nested blocks):

try (
     OutputStream out1 = ...;
     OutputStream out2 = ...;
     InputStream in1 = ...;
     InputStream in2 = ...;
) {
     ...
}

Don't use a try...finally block: that will misbehave for some edge cases (the cases that require a suppressed exception).

Don't use a shutdown-hook: resources are rarely truely gloabl, and that approach will be prone to race hazards. try-with-resources is the recommended manner of properly closing all AutoCloseable resources: the two were introduced to Java at the same time so they can work together.

Doing this implicitly helps implement the (recommended) rule that only the code responsible for creating or opening something is responsible for disposing or closing it: if a method is passed an OutputStream, it should never close() it. It should instead rely on the caller closing it. If none of your methods explicitly call close(), your code is guaranteed never to throw an exception (such as a "Socket closed" java.net.SocketException) because it attempts to use a resource that has been closed.

Doing this ensures that the resource is closed precisely once. Beware that in general it is unsafe to close an AutoCloseable more than once: the close() operation is not guaranteed to be idempotent.

like image 122
Raedwald Avatar answered Sep 18 '22 05:09

Raedwald