skip to content

If multiple resources are declared in one try-with-resources header, in what order are they closed and why?

level: middleimportance: should knowfreq 52%

answer

  1. init left-to-right, close right-to-left
  2. reverse / LIFO / stack order
  3. wrapper closed before the thing it wraps
  4. lets the wrapper flush before the underlying stream closes
  5. all resources still closed even if one close() throws

basics

~10 s

They are closed in the reverse order they were declared. The last one opened is the first one closed, like a stack, so a resource that depends on an earlier one is closed first.

solid answer

~40 s

When you declare several resources in one try-with-resources header, separated by semicolons, they are initialized left to right and closed in the reverse order, last declared first. This LIFO (stack-like) ordering matters because later resources are often built on top of earlier ones: for example a BufferedReader wrapping a FileReader. Closing the wrapper before the underlying stream lets it flush any buffered data while the lower resource is still open, then the lower one closes. Reverse order avoids using an already-closed dependency. The guarantee holds even if an earlier resource's close() throws: the JVM still attempts to close all the remaining resources, and any close() exceptions are recorded as suppressed exceptions rather than aborting the rest of the cleanup.

code

java · 14 lines
java
class R implements AutoCloseable {
    final String name;
    R(String name) { this.name = name; System.out.println("open " + name); }
    @Override public void close() { System.out.println("close " + name); }
}

try (R a = new R("A"); R b = new R("B")) {
    System.out.println("body");
}
// open A
// open B
// body
// close B   <- reverse order
// close A

go deeper

for a junior

Knows multiple resources are separated by semicolons and that closing happens automatically.

for a middle

States the reverse (LIFO) close order and gives the wrapper/underlying-stream rationale.

for a senior

Explains flushing and use-after-close avoidance, and that all resources are still closed when a close() throws (suppressed exceptions).

for a principal

Connects the LIFO teardown to general construction/destruction discipline and designs resource APIs so dependency ordering is safe and obvious.

## Declaring multiple resources You can put more than one resource in a single header, separated by semicolons: ```java try (FileReader fr = new FileReader("a.txt"); BufferedReader br = new BufferedReader(fr)) { System.out.println(br.readLine()); } ``` ## Initialization order: left to right Resources are created **in the order written**: `fr` first, then `br`. That is necessary because `br` is built **from** `fr` — the wrapper needs the thing it wraps to already exist. ## Closing order: reverse (LIFO) When the block exits, resources are closed in the **reverse** of declaration order: `br.close()` first, then `fr.close()`. This is the **last-in-first-out (LIFO)** / stack discipline. ### Why reverse order is correct Resources frequently form a **dependency chain**: a later resource depends on an earlier one (the `BufferedReader` holds the `FileReader`). Two consequences: 1. **Flushing**: a buffered wrapper holds data in memory. Its `close()` flushes that data down to the underlying stream. If the underlying stream were closed first, the flush would fail. Closing the wrapper first, while the lower stream is still open, lets the data reach its destination. 2. **No use-after-close**: closing the higher-level resource may touch the lower-level one. If the lower one were already closed, that would error. Reverse order guarantees a resource is only closed after everything depending on it is closed. This mirrors how local variables / constructors and destructors behave in stack-based languages: you tear down in the opposite order you built up. ## Robustness: all resources are closed The ordering guarantee does not weaken when cleanup fails. If `br.close()` throws, the JVM still calls `fr.close()` afterwards — every declared resource gets a close attempt. The exception(s) from the failing `close()` calls are not silently dropped: they are attached as **suppressed exceptions** (see the suppressed-exceptions topic) to whatever exception ultimately propagates. ## Glossary - **LIFO / stack order**: last item added is the first removed. - **Wrapper / decorator**: an object that wraps another and adds behavior (e.g. buffering), forwarding to it. - **Flush**: push buffered, in-memory data out to the underlying destination. The rule to remember: **initialize left-to-right, close right-to-left**, because the latest resource usually depends on the earlier ones and must be torn down first.

  • Why does closing a BufferedWriter before the underlying FileWriter matter?
    The BufferedWriter holds unwritten data in memory. Its close() flushes that data into the FileWriter, which must still be open to receive it. Reverse order (buffered first) ensures the flush succeeds before the underlying writer closes.
  • If the first-closed resource's close() throws, are the other resources still closed?
    Yes. Each declared resource gets a close() attempt regardless; exceptions from close() are collected as suppressed exceptions rather than aborting the rest of the cleanup.

saying these in an interview costs you the question

  • Saying resources close in declaration order (it is the reverse)
  • Claiming an exception from one close() skips the remaining closes
  • Thinking closing order does not matter for wrapped streams

context