finalizer와 cleaner는 즉시 수행된다는 보장이 없다.
public class FinalizeObject {
@Override
protected void finalize() throws Throwable {
System.out.print("");
}
}
public class FinalizeExample {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
int i = 0;
while (true) {
i++;
new FinalizeObject();
if ((i % 1_000_000) == 0) {
Class<?> finalizerClass = Class.forName("java.lang.ref.Finalizer");
Field queue = finalizerClass.getDeclaredField("queue");
queue.setAccessible(true);
ReferenceQueue<Object> referenceQueue = (ReferenceQueue) queue.get(null);
Field queueLength = ReferenceQueue.class.getDeclaredField("queueLength");
queueLength.setAccessible(true);
long length = (long) queueLength.get(referenceQueue);
System.out.format("There are %d references in the queue\n", length);
}
}
}
}
- finalizer 동작 중에 예외가 발생하면 정리 작업이 처리되지 않을 수 있다.
- finalizer는 보안 문제가 있다.. (구현체의 finalize 메서드를 통해 부모 객체의 메서드를 호출)
- Deprecated since Java 9
public class CleanerObject {
private List<String> resources;
public CleanerObject(List<String> resources) {
this.resources = resources;
}
public static class ResourceCleaner implements Runnable {
private List<String> cleanableResources;
public ResourceCleaner(List<String> cleanableResources) {
this.cleanableResources = cleanableResources;
}
@Override
public void run() {
cleanableResources = null;
System.out.println("Clean the resources");
}
}
}
public class CleanerExample {
public static void main(String[] args) throws InterruptedException {
Cleaner cleaner = Cleaner.create();
List<String> resources = new ArrayList<>();
CleanerObject cleanerObject = new CleanerObject(resources);
cleaner.register(cleanerObject, new CleanerObject.ResourceCleaner(resources));
cleanerObject = null;
System.gc();
Thread.sleep(3000L);
}
}
Clean을 해주는 Runnable 구현체에서 정리하려는 객체를 참조해서는 안된다.
반납할 자원이 있는 클래스는 AutoCloseable을 구현하고 close()를 호출하거나 try-with-resource를 사용
public class CloseableObject implements AutoCloseable{
// try-with-resources에서 실행됨
@Override
public void close() {
System.out.println("Clean the resources");
}
}
public class CloseableExample {
public static void main(String[] args) {
try(CloseableObject closeableObject = new CloseableObject()) {
// 자원 반납 처리 됨
}
}
}
출처 : 백기선 이펙트브 자바 강의
'JAVA' 카테고리의 다른 글
| CountDownLatch (0) | 2025.03.21 |
|---|---|
| Effective Java 클래스와 멤버의 접근 권한을 최소화하라 (1) | 2023.05.18 |
| Effective Java 불필요한 객체 생성을 피하라 (1) | 2023.04.17 |
| Effective Java 의존 객체 주입 (0) | 2023.04.13 |
| Effective Java 싱글턴 part2. (feat. 메서드 참조, 함수형 인터페이스, 직렬화) (1) | 2023.04.11 |