Java는 GC(garbage collection)을 제공하는 언어로 유명하다. 스코프에서 밀려나거나, 어떤 로직에 의해 참조가 끊긴 객체는 garbage collector가 자동으로 메모리를 회수해 간다.
하지만 DB connection이나 File Stream같은 외부 자원을 연결하여 사용하는 객체의 경우 어떻게 해야할까? 다 쓰고 나면 꼭 close()를 호출하여 자원을 회수해 주어야 한다. Garbage collector는 메모리만 회수해 가지, 외부 자원과 약속된 어떤 종료 행위를 실행주지는 않기 때문에 꼭 위와 같은 API나 패키지를 사용한다면 문서를 읽어보고 그에 맞게 close()를 호출 하는 등의 자원 회수 로직을 실행시켜야 한다.
- try-finally 보다는 try-with-resource를 이용하자!
만약 다음과 같은 Stream API를 사용한다고 가정해보자!
OutputStream out = new FileOutputStream(dst);
try{
out.write(....);
} finally {
out.close()
}
자원이 하나라면 나쁘지 않아 보인다. 하지만 자원을 여러개 사용해야 한다면? 밑의 코드처럼 try를 여러번 써야 한다.
SomeStream s = new SomeStream();
try {
OtherStream o = new OtherStream();
try {
s.do_something
o.do_something();
} finally {
o.close();
}
} finally {
s.close();
}
위와 같은 코드를 해결하기 위해 try-with-resource를 사용하자! 단 사용하고자 하는 객체들은 AutoCloseable을 상속해야 한다. 아래와 같이 매우 깔끔한 코드를 작성할 수 있다!
try(SomeStream s = new SomeStream();
OtherStream o = new OtherStream()){
//do something
}
첫번째 예시를 다시 보도록 하자 여기서 큰 문제점이 하나 있는데 만약 write()와 close()두 가지에서 모두 예외가 발생했다면 어떻게 될까? write()서 발생한 예외는 log에 쌓이지 않게 되어 디버깅을 어렵게 한다.
따라서 꼭 try-with-resource를 활용하자. try-with-resource를 사용하면 두 지 모두 log에 남게 된다.