728x90
일반적으로 try-finally 기반으로 해당 처리를 해왔다.
- 그러나 처리해야할 리소스가 많아질수록 코드 퀄리티 가 떨어진다.
- 그리고
close는 자원을 반납하는 것인데, 실수로close를 놓치는 경우도 있다.- 대표적인 메서드로는
InputStream,OutputStream, java.sql.connection등이 있다.
- 대표적인 메서드로는
- 아래 코드에서는 두 로직 다 예외상황이 생길 경우
두 번째 예외가 첫 번째 예외까지 덮어버린다.
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[10];
int n;
while ((n = in.read(buf))>= 0)
out.write(buf, 0, n);
} finally {
out.close();
}
} finally {
in.close();
}
}
- 이러한 코드 형식을 간단히 하기 위해
AutoCloseable과try-with-resources방식이 나왔다.
AutoCloseable 인터페이스
close메서드를 가지고 있는Closeabled의 부모 인터페이스이다. Java 7부터 사용가능했고, 부모 인터페이스이기 때문에 하위성 호환 문제는 없다.close를 어느정도 의무화 시키기 위함이다.- 우선
AutoCloseable로직 메서드를 만들어보자.
class CustomResource implements AutoCloseable {
private String name;
public CustomResource(String name) {
this.name = name;
System.out.println(this.name + " has been opened.");
}
@Override
public void close() throws Exception {
System.out.println(this.name + " closed.");
throw new Exception("Exception from close() of " + this.name);
}
public void doSomething() throws Exception {
System.out.println("Doing something with " + this.name);
// 다음 라인은 `doSomething` 메서드에서 예외를 강제로 발생시킵니다.
throw new Exception("Exception during doSomething of " + this.name);
}
}
- 본 내용을 구현해보자
public class Main {
public static void main(String[] args) {
CustomResource resource = null;
try {
resource = new CustomResource("MyResource");
resource.doSomething();
} catch (Exception e) {
// 이전 예외는 출력하지 않고 넘어갑니다.
// System.out.println("An error occurred: " + e.getMessage());
} finally {
if (resource != null) {
try {
resource.close();
} catch (Exception e) {
System.out.println("Failed to close the resource: " + e.getMessage());
}
}
}
}
}
- 해당 로직을 실행했을 때 두번째 에러 트레이스만 남는다.
doSomething의 예외는 스킵당한다.
MyResource has been opened.
MyResource closed.
Failed to close the resource: Exception from close() of MyResource
try-with-resource 방식으로 전환해보자
- 운영하는 측면에서 많은 로그들이 발생하는데, 문제가 생겼을 때 놓칠 수 있으므로 try-with-resource 방식을 권장하는 것이 좋다고 한다.
- 아래 2개의 error trace 가 잡힌다.
public class Main {
public static void main(String[] args) {
try (AutoCloseableResource resource1 = new AutoCloseableResource("Resource1");
AutoCloseableResource resource2 = new AutoCloseableResource("Resource2")) {
// 예외를 강제로 발생시키는 부분
throw new Exception("Exception from try block");
} catch (Exception e) {
System.out.println("Caught: " + e.getMessage());
for (Throwable suppressed : e.getSuppressed()) {
System.out.println("Suppressed: " + suppressed.getMessage());
}
}
}
}
class AutoCloseableResource implements AutoCloseable {
private String name;
public AutoCloseableResource(String name) {
this.name = name;
System.out.println(this.name + " opened.");
}
@Override
public void close() throws Exception {
System.out.println(this.name + " closed.");
throw new Exception("Exception from close() of " + this.name);
}
}
- 예외 발생 시킬 때
close로 자원을 회수한다. (3, 4 번째 로그)
Resource1 opened.
Resource2 opened.
Resource2 closed.
Resource1 closed.
Caught: Exception from try block
Suppressed: Exception from close() of Resource2
Suppressed: Exception from close() of Resource1728x90
'Programming Language > Java' 카테고리의 다른 글
| [이펙티브 자바]Item.11-equals를 재정의하려거든 hashCode도 재정의하라 (0) | 2024.05.14 |
|---|---|
| [이펙티브 자바]tem.10-equals는일반 규약을 지켜 재정의하라 (0) | 2024.05.14 |
| [Java] 메모리 누수가 발생하는 케이스 (0) | 2024.05.03 |
| [이펙티브 자바]Item.07-다 쓴 객체 참조를 해제하라(+싱글톤) (0) | 2024.05.03 |
| [이펙티브 자바]Item.06-불필요한 객체 생성을 피하라. (0) | 2024.04.06 |