자바 라이브러리에서는 close()로 직접 닫아야 하는 자원이 있다.
ex: InputStream, OutputStream, java.sql.Connectioin
자원닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어질 수 있다.
자원반납시 try-finally의 결점
자원이 제대로 닫힘을 보장하는 수단으로 try-finally를 사용했다.
자바 InputStream 기본 예제로 finally문에서 close하는 예제를 많이 봤을 것이당
static String firstLineOfFile(String path) throws IOException {
final BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
try {
return bufferedReader.readLine();
}finally {
bufferedReader.close();
}
}
이와 같이 finally에서 close()를 하면, finally는 try문 후에 무조건 실행되므로 반드시 자원이 반납됨이 보장된다.
하지만 try, finally문에서 둘 다 예외가 발생할 수 있다!!
위 예제에서 readLine()에서 예외가 발생했다면 finally블록의 close()또한 실패할 것이다.
close()예외가 먼저 발생한 readLine()예외를 집어 삼켜
readLine() 예외에 대한 정보는 남지 않게되고, 디버깅이 어려워진다.
try-with-resources
전제조건: 자원이 AutoClosable인터페이스를 구현해야 한다.
public interface AutoCloseable {
void close() throws Exception;
}
AutoClosable은 위처럼 void를 반환하는 close()만을 정의한 인터페이스이다.
try-with-resources를 사용하면 자동으로 자원을 반납한다.
static String firstLineOfFile(String path, String defaultVal) throws IOException {
final BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
try {
return bufferedReader.readLine();
}catch (IOException ioException){
return defaultVal;
}
}
또한 catch절을 사용해서 다수의 예외를 처리할 수 있다.
catch절을 이용하지 않았을 경우에는 close()예외는 숨겨지고 readLine()에서 발생한 예외만 기록되는데,
숨겨진 예외도 스택 추적 내역에서 확인할 수 있다. (suppressed를 달고 출력됨)
또한 자바 7에서 Throwable에 추가된 getSuppressed()메서드로도 가져올 수 있다.
'Java' 카테고리의 다른 글
[Effective Java] 아이템11. equals를 재정의한다면 hashCode도 재정의하라 (0) | 2022.03.28 |
---|---|
[Effective Java] equals 재정의 일반 규약 (아이템10. equals는 일반 규약을 지켜 재정의하라) (0) | 2022.03.24 |
[Effective Java] 아이템8. finalizer와 cleaner 사용을 피하라 (finalizer/cleaner의 단점, 대안 AutoClosable) (0) | 2022.03.20 |
[Effective Java] 아이템7. 다 쓴 객체 참조를 해제하라 (0) | 2022.03.20 |
[Effective Java] 아이템6. 불필요한 객체 생성을 피하라 (0) | 2022.03.20 |