기본적으로 자바에서는 close 메서드를 통해 작업 완료시 닫아줘야하는 클래스 인스턴스들이 존재한다.
그 예로는 InputStream, OutputStream, java.sql.Connection 등이 있다.
파일처리, 네트워크 연결(socket 등), 데이터베이스 Connection Pool
자원이 제대로 닫힘을 보장하자!
- 개발자가 close 메서드를 놓치는 경우가 존재한다.
- 안전망으로 finalizer 가 있지만 믿을만하지 않다.
1. 전통적인 방법 try-finally
// 자원이 하나인 경우
String path = "/";
BufferedReader br = new BufferedReader(new FileReader(path));
try{
String result = br.readLine();
}
finally {
br.close();
}
// 자원이 두개이상인 경우
String src = "/";
String dst = "/";
InputStream in = new FileInputStream(src);
try{
OutputStream out = new FileOutputStream(dst);
try{
byte[] buf = new byte[10];
int n = 1;
while((n = in.read(buf)) >= 0){
out.write(buf, 0, n);
}
}
finally {
out.close();
}
}
finally {
in.close();
}
2. 두 코드의 문제점
// - 자원이 많아질수록 코드가 지저분해진다.
// - close 메서드를 제대로 구현한 경우가 드문 예시가 많다.
// - try, finally는 모두 예외를 발생시키는데, 만약 try, finally 모두 예외를 발생시킬 문제가 발생된다면
// 첫번째로 발생한 오류는 두번째 오류에 묻히게 되고 이는 디버깅을 어렵게 만든다.
// - 예를들어, 예외발생시 try부분의 예외는 묻히고 close부분의 예외만 발생
3. 해결방법
// 자바7부터는 try-with-sources로 이를 해결
// - 이를 활용하기 위해서는 해당 자원이 AutoCloseable 인터페이스를 구현해야 함.
// - 보통은 만들어진 클래스들은 Closable인터페이스가 AutoCloseable을 구현해놓았음.
// (AutoCloseable 인터페이스는 오직 void를 반환하는 close 메서드만 정의되어 있다.)
// - 닫아야하는 자원을 뜻하는 클래스를 작성한다면 AutoCloseable을 꼭 구현하자.
// - 예외 발생시 try부분의 예외는 기록되고 close 부분에 예외는 숨겨짐.
// - 자바 7에서는 Throwable에 추가된 getSuppressed메서드를 통해 출력 가능
// - 이 후, Catch 절도 작성 가능
// 위의 두가지 예시를 수정
// 아래 코드로 close 역할까지 수행가능
// 1
String path1 = "/";
try(BufferedReader br1 = new BufferedReader(new FileReader(path))){
String result = br1.readLine();
}
// 2
String src1 = "/";
String dst1 = "/";
try(InputStream in1 = new FileInputStream(src);
OutputStream out1 = new FileOutputStream(dst)){
byte[] buf = new byte[10];
int n = 1;
while((n = in1.read(buf)) >= 0){
out1.write(buf, 0, n);
}
}
결론 : Close를 자동으로 사용해주고 코드도 간편하며 오류 발생시 모든 오류를 던져주는 try-with-resources를 사용해 안전하게 자원을 열고 닫자.
코드
https://github.com/mokjaemin/EffectiveJAVA
'Language > Java Plus' 카테고리의 다른 글
Effective JAVA - Item11 : equals를 재정의하려거든 hashcode도 재정의하라. (0) | 2023.09.18 |
---|---|
Effective JAVA - Item10 : equals는 일반 규약을 지켜 재정의하라. (1) | 2023.09.18 |
Effective JAVA - Item8 : finalizer와 cleaner 사용을 피하라 (0) | 2023.09.13 |
Effective JAVA - Item7 : 다 쓴 객체 참조를 해제하라 (0) | 2023.09.12 |
Effective JAVA - Item6 : 불필요한 객체 생성을 피하라. (0) | 2023.09.12 |