Closed icons created by Smashicons - Flaticon
아래와 같은 코드에서 try 블럭 내에서 생성되어 BufferedInputStream에게 전달되는 FileInputStream 인스턴스는 try-with-resources 문에 의해 자동으로 close 되는건지 의문이 생겼다. 이 블로그 글을 쓰신 분에게 도움을 많이 받았다. 결론은 try 블럭 내에서 명시적인 변수로 선언되지 않은 인스턴스는 자동으로 close 되지 않는다.
try (InputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile))) {
dstBuffer.writeBytes(inputStream, (int) srcFile.length());
} ...
그러나 BufferedInputStream 구현을 살펴보면 close할 때 내부 참조 스트림을 함께 닫아주는 것을 볼 수 있다. 위와 같은 상황에서 결론적으로 try-with-resources 문에 의해 닫기가 보장되는 것이 아니라 BufferedInputStream 구현에 의해 닫기가 보장되는 것임을 알 수 있다. try-with-resources 문을 사용할 때 주의가 필요하겠다.
public void close() throws IOException {
byte[] buffer;
while ( (buffer = buf) != null) {
if (U.compareAndSetReference(this, BUF_OFFSET, buffer, null)) {
InputStream input = in;
in = null;
if (input != null)
input.close(); // 내부 참조 스트림을 닫습니다.
return;
}
// Else retry in case a new buf was CASed in fill()
}
}
최종적으로 이해한 것을 테스트 코드로 작성해 보면 다음과 같다.
public class TryWithResourcesTest {
@Test
void notDeclaredAsVariable() throws Exception {
try (Outer outer = new Outer(new Inner())) {
// do something
}
// Result :
// Outer.close()
}
@Test
void declaredAsVariable() throws Exception {
try (Inner inner = new Inner();
Outer outer = new Outer(inner)) {
// do something
}
// Result :
// Outer.close()
// Inner.close()
}
static class Outer implements AutoCloseable {
Inner inner;
Outer(Inner inner) {
this.inner = inner;
}
@Override
public void close() throws Exception {
System.out.println("Outer.close()");
}
}
static class Inner implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("Inner.close()");
}
}
}