자원이란?
Java에서 자원(resource)이란 일반적으로 프로그램이 실행되는 동안 사용되는 외부의 한정된 시스템 자원을 의미한다. 자원은 다양한 형태로 존재하며, 적절히 관리하지 않으면 누수(resource leak)가 발생하거나 시스템 성능에 악영향을 미칠 수 있다. 따라서 자원을 다 쓰고 난 후에는 close와 같은 자원 해제를 해줘야 한다.
Java 7 버전 이전에는 사용하고 난 자원을 반납하기 위해 `try-catch-finally` 구문을 사용했었다. Java 7 버전부터 추가된 `try-with-resources` 구문은 `try` 블록에서 리소스를 선언하고 `try` 블록이 종료되면 자동으로 반납(close)해주는 구문이다.
자원의 예
- 파일: 파일 읽기/쓰기와 관련된 `File` 또는 `FileInputStream`, `FileOutputStream` 등
- 네트워크 소켓: 소켓 연결(`Socket`), 서버 소켓(`ServerSocket`)
- 데이터베이스 연결: `Connection`, `Statement` 등 데이터베이스 관련 객체
- 메모리: 객체 생성 및 사용 중인 힙 메모리
- 쓰레드: 작업 실행을 위해 생성된 Java 쓰레드
- 입출력 스트림: 파일, 콘솔, 네트워크 통신 등 다양한 스트림(`InputStream`, `OutputStream`)
- 운영체제 핸들: 시스템 호출에서 사용하는 리소스
try-catch-finally
Java 7 버전 이전에는 다 사용하고 난 자원을 반납하기 위해 `try-catch-finally`를 이용해서 null 검사와 함께 직접 close 메서드를 호출해주어야 했다.
public static void main(String args[]) throws IOException {
FileInputStream is = null;
BufferedInputStream bis = null;
try {
is = new FileInputStream("file.txt");
bis = new BufferedInputStream(is);
int data = -1;
while((data = bis.read()) != -1){
System.out.print((char) data);
}
} finally {
// close resources
if (is != null) is.close();
if (bis != null) bis.close();
}
}
`finally` 블록은 예외가 발생하더라도 항상 실행되는 블록으로, 자원 해제 코드를 작성하면 자원을 항상 안전하게 해제할 수 있다.
문제점
- 자원 반납에 의해 코드가 복잡해진다.
- 작업이 번거롭다.
- 실수나 에러로 자원을 반납하지 못하는 경우 발생
- 에러 스택 트레이스가 누락되어 디버깅이 어려움
이러한 문제를 해결하기 위해 `try-with-resources`라는 문법이 Java7부터 추가되었다.
try-with-resources
AutoCloseable 인터페이스를 구현한 자원들에 한정해서, 자원을 자동으로 반납해준다. `try-catch-finally` 구문과 달리 `try` 옆에 괄호 안에서 리소스를 생성한다.
public static void main(String args[]) throws IOException {
try (FileInputStream is = new FileInputStream("file.txt"); BufferedInputStream bis = new BufferedInputStream(is)) {
int data;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
}
}
위 예제와 같이 `;`로 구분하여 여러 리소스를 생성할 수 있다.
아래와 같은 이유로 반드시 `try-with-resources`를 사용해주어야 한다.
- 코드를 간결하게 만들 수 있음
- 번거로움 자원 반납 작업을 하지 않아도 됨
- 실수나 에러로 자원을 반납하지 못하는 경우를 방지할 수 있음
- 모든 에러에 대한 스택 트레이스를 남길 수 있음
자세한 내용을 알고 싶으면 이 분의 글을 참고하길!
Custom Resource 생성하기
AutoCloseable 인터페이스를 구현하여, 사용자가 리소스 클래스를 생성할 수도 있다.
public class CustomResource implements AutoCloseable {
public CustomResource() {
System.out.println("CustomResource Constructor");
}
public void printMessage() {
System.out.println("CustomResource Print Message");
}
@Override
public void close() throws Exception {
System.out.println("CustomResource close");
}
}
public class ResourceClose {
public static void main(String[] args) {
try (CustomResource cr = new CustomResource()) {
cr.printMessage();
} catch (Exception e) {
e.printStackTrace();
}
}
}
[ 결과 ]
CustomResource Constructor
CustomResource Print Message
CustomResource close
참조
https://mangkyu.tistory.com/217
https://hianna.tistory.com/546
'Java' 카테고리의 다른 글
[Java/김영한] 접근 제어자 (0) | 2025.01.16 |
---|---|
[Java] Stream (1) | 2024.11.17 |
[Java] static (0) | 2024.11.08 |
[Java] Enum이란? (0) | 2024.11.01 |
[AssertJ] Custom Exception (0) | 2024.10.31 |