Try-with-resources in Java β€” Auto-closing Resources

Try-with-resources (Java 7+) is a try block that automatically closes any resource declared in its header β€” as long as the resource implements AutoCloseable. It replaces the verbose, bug-prone try/finally { resource.close(); } pattern.

Basic syntax

try (var reader = Files.newBufferedReader(path)) {
    return reader.readLine();
}
// reader.close() called automatically β€” success or failure

Multiple resources

try (var in  = Files.newInputStream(src);
     var out = Files.newOutputStream(dst)) {
    in.transferTo(out);
}
// Both close β€” in reverse order: out first, then in

Existing variables (Java 9+)

BufferedReader r = openSpecial();    // declared elsewhere
try (r) {                             // Java 9+ β€” no re-declaration needed
    r.readLine();
}

Suppressed exceptions

If the try body throws and close() also throws, Java keeps both β€” the body exception is the main one; the close exception is suppressed:

try {
    work();
} catch (Exception e) {
    for (Throwable t : e.getSuppressed()) {
        log.warn("suppressed", t);
    }
    throw e;
}

Writing your own AutoCloseable

public class Session implements AutoCloseable {
    public void send(Message m) { ... }
    @Override
    public void close() {
        // no need to throw checked exceptions β€” declare only what you throw
        ...
    }
}

try (var s = new Session()) {
    s.send(msg);
}

Prefer AutoCloseable over Closeable β€” the former allows any checked exception (or none) in close().

Classes that support it

  • I/O: InputStream, OutputStream, Reader, Writer, Files.newBufferedReader(...), ZipFile.
  • JDBC: Connection, Statement, ResultSet β€” since JDBC 4.1.
  • Concurrency: ExecutorService (Java 19+).
  • Java NIO: FileChannel, SocketChannel, DirectoryStream.

Common mistakes

  • Using try/finally manually β€” try-with-resources is cleaner, handles suppressed exceptions, and never forgets the null check.
  • Assigning the resource twice inside the try β€” only the header declaration is auto-closed.
  • Assuming close() can throw everything β€” the resource's close() declares what it throws; your catches only cover those.

Related

Pillar: Java exceptions. Sibling: try/catch/finally.