소프트 참조(SoftReference)는 주로 메모리 상황에 민감하게 동작하는 캐시를 구현할 때 널리 활용됩니다. 가비지 컬렉터는 JVM의 메모리가 부족할 때만 소프트 참조된 객체를 회수하기 때문에, 캐시 용도로 매우 적합합니다. 그럼 자바에서 소프트 참조를 사용하는 예제를 살펴보겠습니다.
소프트 참조 예제
import java.lang.ref.SoftReference;
class Demo{
public void display_msg(){
System.out.println("Hello there");
}
}
public class Demo_example{
public static void main(String[] args){
Demo my_instance = new Demo();
my_instance.display_msg();
SoftReference<Demo> my_softref = new SoftReference<Demo>(my_instance);
my_instance = null;
my_instance = my_softref.get();
my_instance.display_msg();
}
}실행 결과
Hello there Hello there
코드 설명
'Demo'라는 클래스에는 메시지를 화면에 출력하는 'display_msg' 함수가 정의되어 있습니다. main 함수를 포함하는 또 다른 클래스 'Demo_example'에서는 먼저 Demo 클래스의 인스턴스를 생성하고, 해당 인스턴스에서 'display_msg' 함수를 호출합니다.
이후 Demo 클래스에 대한 SoftReference 객체를 생성하고, 원래 강한 참조(strong reference) 변수에는 null을 할당합니다. 다음으로 소프트 참조 객체의 'get()' 함수를 호출해 객체를 다시 얻은 뒤, 이 인스턴스에서 'display_msg' 함수를 호출하면 콘솔에 메시지가 정상적으로 출력됩니다. 즉, 메모리가 충분한 상황에서는 소프트 참조를 통해서도 객체에 계속 접근할 수 있다는 것을 보여주는 예제입니다.
팬텀 참조(PhantomReference)란?
팬텀 참조는 자바의 파이널라이제이션(finalization) 메커니즘보다 훨씬 유연한 방식으로, 객체가 회수되기 전에 필요한 사전 정리(pre-mortem cleanup) 작업을 예약할 때 사용됩니다.
그럼 이어서 팬텀 참조의 예제를 살펴보겠습니다.
팬텀 참조 예제
import java.lang.ref.*;
class Demo{
public void display_msg(){
System.out.println("Hello there");
}
}
public class Demo_example{
public static void main(String[] args){
Demo my_instance = new Demo();
my_instance.display_msg();
ReferenceQueue<Demo> refQueue = new ReferenceQueue<Demo>();
PhantomReference<Demo> phantomRef = null;
phantomRef = new PhantomReference<Demo>(my_instance,refQueue);
my_instance = null;
my_instance = phantomRef.get();
my_instance.display_msg();
}
}실행 결과
Hello there Exception in thread "main" java.lang.NullPointerException at Demo_example.main(Demo_example.java:22)
코드 설명
'Demo' 클래스에는 메시지를 출력하는 'display_msg' 함수가 정의되어 있으며, main 함수를 담고 있는 'Demo_example' 클래스에서 Demo 인스턴스를 생성한 뒤 'display_msg' 함수를 호출합니다.
그다음 ReferenceQueue 인스턴스를 생성하고, PhantomReference 변수를 null로 초기화합니다. 이후 Demo 인스턴스와 참조 큐를 인자로 전달해 팬텀 참조를 생성한 뒤, 원본 참조를 null로 만듭니다. 마지막으로 'get()' 함수를 통해 객체를 다시 얻으려 시도하지만, 팬텀 참조의 get() 함수는 항상 null을 반환하므로 'display_msg'를 호출하는 시점에 NullPointerException이 발생합니다.
이러한 결과가 바로 팬텀 참조의 핵심 특징입니다. 팬텀 참조로는 참조 대상 객체에 직접 접근할 수 없으며, 오직 객체가 수거 대상이 되었는지 확인하고 사후 처리 작업을 수행하는 용도로만 사용됩니다. 이는 리소스 해제나 정리 로직을 안전하게 처리하고자 할 때 유용하게 활용됩니다.