코딩하는 털보

이펙티브 자바, 아이템 7. 다 쓴 객체 참조를 해제하라 본문

Book/이펙티브 자바

이펙티브 자바, 아이템 7. 다 쓴 객체 참조를 해제하라

이정인 2021. 8. 18. 16:41

이펙티브 자바, 아이템 7. 다 쓴 객체 참조를 해제하라

자바의 가비지 컬렉터는 다 쓴 객체를 알아서 회수해가지만 그렇다고 메모리 관리에 더 이상 신경 쓰지 않아도 되는 것은 아니다.
가비지 컬렉션 언어에서는 메모리 누수를 찾기가 아주 까다롭다. 객체 참조 하나를 살려두면 가비지 컬렉터는 그 객체뿐아니라 그 객체가 참조하는 모든 객체를 회수해가지 못한다. 그래서 단 몇 개의 객체가 매우 많은 객체를 회수되지 못하게 할 수 있고 잠재적으로 성능에 악영향을 줄 수 있다.

해법은 참조해제. 해당 참조를 다 썼을 때 null 처리하면 된다.

    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        Object result = elements[--size];
        elements[--size] = null; // 다 쓴 객체 참조 해제
        return result;
    }
  • 객체 참조를 null 처리하는 일은 스택처럼 자기 메모리를 직접 관리하는 클래스에서 처럼 예외적인 경우여야 한다. 참조 해제의 가장 좋은 방법은 그 참조를 담은 변수를 유효 범위 밖으로 밀어내는 것이다.

  • 캐시
    캐시 역시 메모리 누수를 일으키는 주범이다.
    캐시 외부에서 키를 참조하는 동안만 엔트리가 살아 있는 캐시가 필요한 상황이라면 WeakHashMap를 사용해 캐시를 만들자. 다 쓴 엔트리는 자동으로 제거된다.
    보통 캐시 엔트리의 유효 기간을 정의하기 어려우므로 시간이 지날수록 엔트리의 가치를 떨어뜨리는 방식을 사용한다. 이런 방식에서는 쓰지 않는 엔트리를 이따금 청소해줘야 하는데, 백그라운드 스레드를 활용하거나 새 엔트리를 추가할 때 부수 작업으로 수행하는 방법(예를 들어 LinkedHashMap의 removeEldestEntry 메서드)이 있다.

  • 리스너 혹은 콜백
    클라이언트가 콜백을 등록만 하고 명확히 해지하지 않는다면 콜백은 계속 쌓여갈 것이다. 이럴 때 콜백을 약한 참조로 저장하면 가비지 컬렉터가 즉시 수거해간다. 예를들어 WeakHashMap에 키로 저장하면 된다.

  • 핵심 정리
    메모리 누수는 찾기 어려우므로 예방법을 익혀두는 것이 매우 중요하다.

Comments