Java Reference
- 
    
strong > soft > weak > (phantom ?) > unreachable
 - 
    
오른쪽으로 갈수록 GC의 수거 대상 확률이 높아진다.
 
Strong Reference
- 
    
먼저 우리가 일반적으로 쓰고있는 Strong reference이다.
 - 
    
이런식의 참조는 절대 GC가 되지 않는다.
 
public class ClassStrong {
 
    public static class Referred {
        protected void finalize() {
            System.out.println("Good bye cruel world");
        }
    }
 
    public static void collect() throws InterruptedException {
        System.out.println("Suggesting collection");
        System.gc();
        System.out.println("Sleeping");
        Thread.sleep(5000);
    }
 
    public static void main(String args[]) throws InterruptedException {
        System.out.println("Creating strong references");
 
        // This is now a strong reference.
        // The object will only be collected if all references to it disappear.
        Referred strong = new Referred();
 
        // Attempt to claim a suggested reference.
        ClassStrong.collect();
 
        System.out.println("Removing reference");
        // The object may now be collected.
        strong = null;
        ClassStrong.collect();
 
        System.out.println("Done");
    }
}
Soft Reference
- 
    
이 경우 JVM의 GC가 메모리가 부족하다고 판단하면 수거해간다.
 - 
    
GC가 수거해가지 못하도록 방지하는 수준은 아니지만 (이거는 strong reference), 수거 시간을 지연할 수는 있다.
 - 
    
GC가 수거해가지 못하도록 하는 수준은 아니지만(=Strong Reference)
수거 시간을 지연할 수는 있다. - 
    
자주 사용될수록 GC가 수거해가지 않는다.
 - 
    
[Soft Reference가 참조하고 있는 객체가 마지막으로 사용된 이후로부터 지금까지의 시간] > [옵션 설정값 N] * [힙에 남아있는 메모리 크기]
 - 
    
위 조건이 만족되면 GC가 수거해간다.
 - 
    
위의 옵션 설정값 N 은 JVM 옵션 설정값으로 다음과 같이 정해준다.
-XX:SoftRefLRUPolicyMSPerMB= 
- 
    
따라서 원문에서는 캐쉬(cache)로 사용하면 좋다고 언급하지만
 - 
    
사실 Soft Reference는 캐쉬로 사용하면 안된다.
 - 
    
간략하게 설명하자면 soft reference로 인해 메모리에 GC threshold까지 계속 차있는 상태가 유지되면
 - 
    
훨씬더 잦은 GC를 발생시킨다.
 
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
 
/*
 * A sample for Detecting and locating memory leaks in Java
 */
public class ClassSoft {
 
    public static class Referred {
        protected void finalize() {
            System.out.println("Good bye cruel world");
        }
    }
 
    public static void collect() throws InterruptedException {
        System.out.println("Suggesting collection");
        System.gc();
        System.out.println("Sleeping");
        Thread.sleep(5000);
    }
 
    public static void main(String args[]) throws InterruptedException {
        System.out.println("Creating soft references");
 
        // This is now a soft reference.
        // The object will be collected only if no strong references exist and the JVM really needs the memory.
        Referred strong = new Referred();
        SoftReference<Referred> soft = new SoftReference<Referred>(strong);
 
        // Attempt to claim a suggested reference.
        ClassSoft.collect();
 
        System.out.println("Removing reference");
        // The object may but highly likely wont be collected.
        strong = null;
        ClassSoft.collect();
 
        System.out.println("Consuming heap");
        try
        {
            // Create lots of objects on the heap
            List<ClassSoft> heap = new ArrayList<ClassSoft>(100000);
            while(true) {
                heap.add(new ClassSoft());
            }
        }
        catch (OutOfMemoryError e) {
            // The soft object should have been collected before this
            System.out.println("Out of memory error raised");
        }
 
        System.out.println("Done");
    }
}
Weak Reference
- 
    
가장 흔하게 쓰는 Reference이다.
 - 
    
명시적으로 Weak Reference를 사용하여 해당 객체가 GC 되도록 유도할 수 있다.
 - 
    
일단 GC가 돌면은 수거해가는 객체들이다.
 
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
 
/*
 * A sample for Detecting and locating memory leaks in Java
 */
public class ClassWeak {
 
    public static class Referred {
        protected void finalize() {
            System.out.println("Good bye cruel world");
        }
    }
 
    public static void collect() throws InterruptedException {
        System.out.println("Suggesting collection");
        System.gc();
        System.out.println("Sleeping");
        Thread.sleep(5000);
    }
 
    public static void main(String args[]) throws InterruptedException {
        System.out.println("Creating weak references");
 
        // This is now a weak reference.
        // The object will be collected only if no strong references.
        Referred strong = new Referred();
        WeakReference<Referred> weak = new WeakReference<Referred>(strong);
 
        // Attempt to claim a suggested reference.
        ClassWeak.collect();
 
        System.out.println("Removing reference");
        // The object may be collected.
        strong = null;
        ClassWeak.collect();
 
        System.out.println("Done");
    }
}
LRU 캐시 구현
- 
    
LRU 캐시 구현에 Soft Reference가 적합하다는 의견이 있다.
 - 
    
Weak Reference가 적합하다는 의견도 있다.
 - 
    
Soft Reference가 적합하다고 하는 이유는
Soft Reference 자체적으로 최근에 사용될수록 GC에서 수거해가지 않는 속성이 있기 때문에
LRU 전략(Least Recently Used)을 바로 구현할 수 있기 때문이다. - 
    
Weak Reference가 적합하다고 하는 이유는
다른 logic을 위해 비워야할 Heap 공간이 Soft Reachable 객체들에 의해 점유되기 때문에
메모리 사용량이 늘고 따라서 GC 가 자주 돌게 되고 이는 성능 이슈를 만든다. - 
    
즉 Soft로 선언했기 때문에 자주 사용되지 않아도 메모리에 남아있을 가능성이 있기 때문에
Weak처럼 안쓰면 바로바로 회수를 하여 실질적으로 많이 참조되는 객체만 살아남도록하자는 방식이다.