아이템 7 - 다 쓴 객체 참조를 해제하라.
JAVA
·
어떤 객체에 대한 레퍼런스가 남아있다면 해당 객체는 가비지 컬렉션의 대상이 되지 않는다.
- 해결법으로 참조를 다 썼을 때 null 처리를 해도 되지만, 프로그램을 필요 이상으로 지저분하게 만듦.
- 가장 좋은 방법은 참조를 담은 변수를 유효 범위 밖으로 밀어내는 것.
자기 메모리를 직접 관리하는 클래스라면 메모리 누수에 주의해야 한다.
- 예) 스택, 캐시, 리스너 또는 콜백
- 캐시 외부에서 키를 참조하는 동안만 엔트리가 살아 있는 캐시가 필요한 상황이면 WeakHashMap을 사용해 캐시를 만들어라.
- 다 쓴 엔트리는 자동으로 제거됨
- WeakHashMap은 이런 상황에서만 유용
- 보통 캐시 엔트리의 유효 기간을 정확히 정의하기 어렵기 때문에, 쓰지 않는 엔트리를 청소해줘야 한다. 백그라운드 스레드를 활용하거나 캐시에 새 엔트리를 추가할 때 오래된 엔트리를 지운다.
- 클라이언트가 콜백을 등록만 하고 명확히 해지하지 않는다면 콜백은 계속 쌓인다. 이럴 때 콜백을 약한 참조로 저장하면 가비지 컬렉터가 즉시 수거해 간다.
WeakHashMap
- 더 이상 사용하지 않는 객체를 GC할 때 자동으로 삭제해주는 Map
- Key가 더 이상 강하게 레퍼런스되는 곳이 없다면 해당 엔트리를 제거한다.
- 레퍼런스 종류 : Strong, Soft, Weak, Phantom
- Strong 레퍼런스 : 보통 우리가 할당하는 방식(new), null 할당시 GC 대상이 됨.
- Soft 레퍼런스 : new SoftReference<클래스명>(변수명) 형태로 할당, 메모리가 필요한 순간에만 GC 됨.클래스명>
- Weak 레퍼런스 : new WeakReference<클래스명>(변수명) 형태로 할당, GC가 일어나면 바로 수거됨.클래스명>
- Phantom 레퍼런스 : new PhantomReference<클래스명>(변수명, 레퍼런스큐 변수명) 형태로 할당, GC 시에 레퍼런스 큐에 저장됨. 자원 반납할 때 사용될 수 있지만, 거의 사용하지 않음.클래스명>
- 맵의 엔트리를 맵의 Value가 아니라 Key에 의존해야 하는 경우에 사용할 수 있다.
- Key 객체는 직접 구현한 객체를 사용해야 GC가 되고, Integer 같은 값을 사용하면, 어디선가 강하게 레퍼런스 되고 있을 수 있어 GC가 안될 수 있다.
- 캐시를 구현하는데 사용할 수 있지만, 캐시를 직접 구현하는 것은 권장하지 않는다.
출처
이펙티브 자바 3/E
이펙티브 자바 완벽 공략 1