Java의 try-with-resources는 선언한 자원을 초기화한 순서와 반대로 닫습니다. 두 자원 A와 B를 이 순서로 선언하면 본문이 끝난 뒤 B를 닫고 다음 A를 닫습니다. 본문에서 예외가 발생해도 자원 정리를 진행합니다.

본문 예외가 주 예외로 남고 close에서도 예외가 나면 정리 중 생긴 예외는 suppressed 예외로 연결될 수 있습니다. 본문·종료 순서·예외 종류를 각각 기록해야 합니다.

선언 순서대로 열고 역순으로 닫습니다

try-with-resources의 자원은 선언될 때 왼쪽에서 오른쪽 순서로 초기화됩니다. 블록을 벗어날 때는 그 반대로 닫습니다. 따라서 A를 먼저 선언하고 B를 나중에 선언하면 B의 close()가 먼저 실행된 뒤 A의 close()가 실행됩니다. 이는 중첩된 자원에서 안쪽 자원을 먼저 정리하는 흐름과 맞닿아 있습니다. 추적 문제에서는 선언을 한 줄씩 기록한 다음, 종료 단계에서 목록을 뒤집어 보는 것이 간단합니다.

본문 예외가 발생해도 두 자원을 닫습니다

close가 로그를 남기고 예외를 던지는 교육용 가상 자원 예시입니다.
try (Resource a = open("A");
     Resource b = open("B")) {
  log("body");
  throw new WorkException();
}
초기화·본문·정리 로그를 시간 순서로 씁니다
순서행동예외 역할
1A 초기화없음
2B 초기화없음
3본문 실행 후 WorkException 발생주 예외 후보
4B.close()여기서 난 예외는 suppressed 예외로 남을 수 있음
5A.close()여기서 난 예외도 suppressed 예외로 남을 수 있음

본문에서 예외가 없고 B와 A의 close도 정상이라면 정리는 B, A 순서로 끝납니다. 본문에서 WorkException이 발생하고 두 close도 각각 예외를 던진다면, 본문 예외가 호출자에게 전달되는 주 예외가 되고 close에서 발생한 예외들은 suppressed 예외로 보관됩니다. Throwable.getSuppressed()로 그 예외를 확인할 수 있습니다. 반대로 본문은 정상인데 close에서 예외가 나면, 자원 종료 중 먼저 전달되는 close 예외와 나머지 예외의 관계를 구체 코드로 따로 추적해야 합니다.

예외를 하나로 뭉개지 말고 순서대로 분류합니다

  1. 자원 선언과 초기화 순서를 적습니다.
  2. 본문의 정상 완료 또는 발생 예외를 적습니다.
  3. close 순서를 선언 순서의 역순으로 정합니다.
  4. 본문과 각 close가 던지는 예외를 주 예외와 suppressed 예외로 분리합니다.
  5. 필요하면 AutoCloseable.close가 선언한 예외 허용 범위를 확인합니다.

close가 먼저 선언한 순서로 실행된다고 착각하지 않습니다

자원을 A, B 순으로 적었다고 close도 A, B 순서일 것이라고 외우면 역순 정리 문제를 틀립니다. 또 close()에서 발생한 예외가 모두 사라진다고 생각하면 진단 정보를 놓칩니다. 본문 예외가 이미 존재하면 close 예외는 suppressed로 남을 수 있습니다. 실제로는 여러 자원 초기화가 실패하거나 특정 자원이 null인 경우도 있으므로, 이번 예제의 단순한 두 자원 흐름을 모든 경우의 완전한 예외 우선순위표로 오해하지 마세요.

뒤 자원 초기화가 실패해도 먼저 성공적으로 초기화된 자원은 정리 대상이 될 수 있습니다. 예를 들어 A를 만든 뒤 B 생성 과정에서 예외가 발생하면 A의 close가 실행되고, 정리 중 예외가 나면 원래 실패와 함께 보존될 수 있습니다. 이 흐름은 자원 누수를 막는 중첩 try-finally 규칙과 연결됩니다. 하지만 어떤 자원이 생성되었는지, 본문이 실행되었는지, 각 close가 예외를 던졌는지를 확인하지 않고 모든 예외를 같은 순서로 나열하면 오답입니다. 먼저 생성 성공 여부를 표시하고, 살아 있는 자원을 역순으로 정리하세요.

정답을 가리고 확인해 보세요

이 글을 위해 만든 학습 예시이며 공식 기출문제나 판매 카드의 인용이 아닙니다.

A, B 순서로 선언한 자원의 close 순서와 본문 예외가 있을 때 close 예외의 위치를 설명하세요.

정답과 해설 확인B를 먼저 닫고 A를 닫습니다. 본문 예외가 주 예외로 유지되며 close 예외는 suppressed 예외로 연결될 수 있습니다.

Java SE 21 JLS try-with-resources 규칙과 AutoCloseable 계약을 적용합니다. 예제의 예외 흐름은 본문 예외가 발생한 경우로 한정합니다.