DAUM DNA에 올라왔던 글을 보며 정리합니다.

Rechability(접근성)이라는 단어를 처음 보게 됐습니다. 어떤 객체에 접근할 수 있는 reference의 강도를 네 단계로 구분 해 두었습니다.

Strong reference > Soft reference > Weak reference > Phantom reference

Strong reference는 new를 사용하여 객체를 생성할 때 생기는 reference를 말하며 어떤 객체를 참조 하고 있는 Strong reference가 존재하는 이상 그 객체는 GC의 수거 대상이 되지 않습니다.

Soft reference는 GC의 대상이 될 수도 있고 안 될 수도 있는데 Out of memory가 발생할 상황이라면 무조건 수거가 되고 그렇치 않다면 살아 남는 레퍼런스 입니다.

Weak reference는 GC가 발동하기 전까지는 살아 있지만 GC가 일단 발동하는 순간 제거가 되버리는 레퍼런스 입니다.(맨 끝에 사용되는 예제가 나옵니다.)

Phantom reference는 이 레퍼런스를 통해 객체에 접근하려고 하면 null 값만 리턴합니다. 즉 접근할 수가 없습니다. 그렇다고 객체가 없어진 것은 아니고 다만 객체가 수거 될 때 사후 처리를 위해 사용한다고 합니다.(어떻게 사용되는지 예가 보고 싶은데 조금더 찾아봐야겠습니다.)

Strong reference를 생성하는 방법은 일반적인 객체의 레퍼런스를 생성하는 방식과 같으며
Strong reference를 제외한 다른 reference들은 모두 Soft reference를 생성하는 방식으로 만들어집니다.

Date endDate = new Date();
//Date 객체의 접근성은 Strongly Rechable 하다고 할 수 있겠습니다.
SoftReference sr = new SoftReference(endDate);
//Date 객체의 soft reference는 위의 방식 처럼 생성합니다. 하지만 여전히 Date 객체의 Strong reference(endDate)가 존재하기 때문에 이 객체의 접근성은 Strongly Rechable 합니다.
endDate = null;
//이 순간 Strong reference는 끊기게 되며 이제 이 객체의 접근성은 Softly rechable 하다고 할 수 있겠습니다.

마지막으로 Weak Reference를 사용하는 예제를 보겠습니다.

SimpleCache.java 소스보기 (출처 : http://dna.daum.net/technote/java/JavaReferenceObjects)
[#M_ more.. | less.. |
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

public class SimpleCache {
   private Map map = new HashMap();

   public void put(String key, Object value) {
       map.put(key, new WeakReference(value));
   }

   public Object get(String key) {
       Object obj = map.get(key);
       return ((WeakReference) obj).get();
   }
}
_M#]
SimpleChacheTest.java 소스보기 (출처 : http://dna.daum.net/technote/java/JavaReferenceObjects)
[#M_ more.. | less.. |
import junit.framework.TestCase;

public class SimpleCacheTest extends TestCase {
   public void testCache() {
       String key = new String("Key");
       String value = new String("" + Math.random());

       SimpleCache cache = new SimpleCache();
       cache.put(key, value);

       value = null;

       assertNotNull(cache.get(key));   // Garbage collection 이전에는 value가 존재함.
       System.gc();
       assertNull(cache.get(key));        // value가 사라짐.
   }
}
_M#]
결과
1008451819.bmp

흠.. weak reference로 참조되는 객체는 GC가 발동하면 바로 제거가 되기 때문에 System.gc()를 호출 하는 것 만으로 객체를 제거할 수 있게 되는 군요. 신기하네요. :)