[JAVA] try-finally 쓰지 마세요
요약
finally
는 deprecate
될 예정입니다.
향후 릴리스에서는 기본적으로 비활성화되며, 이후 릴리스에서는 제거될 예정입니다.
finally
를 사용하는 라이브러리 및 애플리케이션의 유지 관리자는 try-with-resources
및 cleaners
와 같은 다른 리소스 관리 기법으로 마이그레이션해야 합니다.
finally
의 위험성: 리소스 누수
파일 디스크립터(File descriptor)나 네이티브 메모리 블록(Native memory block)과 같이 운영 체제에서 제공하는 리소스를 사용하는 객체가 있습니다.
이러한 객체의 경우 단순히 객체의 메모리를 회수하는 것만으로는 충분하지 않으며, 프로그램은 일반적으로 객체의 close
와 같은 메서드를 호출하여 기본 리소스를 운영 체제에 다시 릴리스해야 합니다.
GC가 객체를 회수하기 전에 프로그램이 이 작업을 수행하지 못하면 리소스를 해제하는 데 필요한 정보가 손실됩니다.
운영 체제에서 여전히 사용 중인 것으로 간주되는 리소스에 누수가 발생한 것입니다.
아래 코드는 한 파일에서 다른 파일로 데이터를 복사합니다.
복사하는 동안 예외가 발생하더라도 리소스가 해제되도록 try-finally 구문을 사용했습니다.
FileInputStream input = null;
FileOutputStream output = null;
try {
input = new FileInputStream(file1);
output = new FileOutputStream(file2);
// ... copy bytes from input to output ...
output.close(); output = null;
input.close(); input = null;
} finally {
if (output != null) output.close();
if (input != null) input.close();
}
이 코드는 잘못되었습니다.
복사가 예외를 발생시키고 finally
블록의 output.close()
에서 예외를 발생하면 input
스트림이 유출됩니다.
이를 막기 위해서는 중첩된 try-finally
를 사용해야 하는데, 가능한 모든 실행 경로에서 예외를 처리하는 것은 힘들고 제대로 처리하기 어렵습니다.
그 외에도 finally
에는 여러 결함이 있습니다.
해당 부분에 대해서는 참고를 참고하십시오.
finally
의 대안: try-with-resources
try (FileInputStream input = new FileInputStream(file1);
FileOutputStream output = new FileOutputStream(file2)) {
// ... copy bytes from input to output ...
}
Java 7은 try-finally
구문을 개선하기 위해 try-with-resources
를 도입했습니다.
try-with-resources
를 사용하면 예외 발생 여부에 관계없이 해당 메서드의 close()
메서드 호출이 보장되는 방식으로 리소스를 사용할 수 있습니다.
finally
의 대안: Cleaner
Cleaner
는 잘 안 사용해봐서 모르겠으나 Cleaner
를 사용하는 방법도 있습니다.
그런데 Effective Java에서는 Cleaner
를 사용하지 말라고 되어있는 것 같습니다?(읽어보진 않음)
Comments