자바 라이브러리에는 close 메서드를 직접 호출해 닫아줘야 하는 자원들이 있다.
ex) InputStream, OutputStream, java.sql.Connection 등
이런 자원 중 상당수가 안전망으로 finalizer를 활용하고는 있지만 그리 믿을만하지 못하기 때문에 클라이언트가 자원 닫기를 놓치는 경우 예측할 수 없는 성능 문제로 이어지기도 한다.
👉 전통적인 자원 닫기 방법
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}
위 방법에서 닫아야 할 자원이 두개 이상일 경우
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
out.close();
}
} finally {
in.close();
}
}
두 예제 코드 모두에 미묘한 결점이 있다. 기기에 물리적인 문제가 생긴다면 readLine()이 예외를 던지고, 같은 이유로 close()도 실패하게 되는데 이럴 경우 두 번째 예외가 첫 번째 예외를 집어삼켜 버린다.
그러면 스택 추적 내역에 첫 번째 예외에 대한 정보가 남지 않게 되어 디버깅이 어렵게 된다. (첫 번째 예외를 기록하도록 코드를 수정할 수 있긴 하다.)
👉 try-with-resources
자바 7에서 생겼다.
이 구조를 사용하려면 해당 자원이 AutoCloseable 인터페이스를 구현해야 한다.
이 버전이 더 짧고 읽기 수월할 뿐 아니라 문제를 진단하기도 훨씬 좋다.
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
return br.readLine();
}
}
static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
readLine()과 close()(코드에 나타나진 않지만) 호출 양쪽에서 예외가 발생하면 close()에서 발생하는 예외는 숨겨지고 readLine()에서 발생한 예외가 기록된다.
프로그래머에게 보여줄 예외 하나만 보존되고 나머지 여러개의 다른 예외는 숨겨질 수 있는데 숨겨진 경우 스택 추적 내역에 suppressed 꼬리표를 달고 출력된다. 혹은 자바 7에서 Throwable에 추가된 getSuppressed()를 이용해 프로그램 코드에서 가져올 수도 있다.
그 외 예외처리가 필요한 경우
보통의 try-finally 처럼 catch 절을 쓸 수 있어 try 문을 중첩하지 않고도 다수의 예외를 처리할 수 있다.
'reviews > Effective JAVA' 카테고리의 다른 글
011. equals를 재정의하려거든 hashCode도 재정의하라 (0) | 2022.04.21 |
---|---|
010. equals는 일반 규약을 지켜 재정의하라 (0) | 2022.04.07 |
007. 다 쓴 객체 참조를 해제하라 (0) | 2022.03.09 |
006. 불필요한 객체 생성을 피해라 (0) | 2022.03.04 |
005. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2022.02.25 |