[아이템7] 다 쓴 객체 참조를 해제하라

ds_chanin

·

2020. 1. 28. 14:59


아이템 7 다 쓴 객체 참조를 해제하라

메모리 누수의 주범이다.

사용을 마친 객체의 참조를 해제할 때 null을 이용하여 객체 참조를 해제하는 방법도 있지만, 이는 지양하도록 하라.
가장 이상적인 방법은 참조를 담은 변수를 유효 범위 밖으로 밀어내는 것이다.

캐시 또한 메모리 누수를 일으키는 주범이니, 캐시 외부에서 키를 참조하는 동안만 엔트리가 살아 있는 캐시가 필요하다면 WeakHashMap을 사용해 캐시를 만들도록 하자.

    @DisplayName("HashMap 테스트")
    @Test
    void test1() {
        //given
        Map<Foo, String> map = new HashMap<>();

        Foo key = new Foo();
        map.put(key, "1");

        //when
        key = null;
        System.gc();

        //then
        assertAll(
                "HashMap 은 참조를 끊어도 map 이 비어있지 않다.",
                () -> assertThat(map.isEmpty()).isFalse()
        );

    }

    @DisplayName("WeakHashMap 테스트")
    @Test
    void test2() {
        //given
        Map<Foo, String> map = new WeakHashMap<>();

        Foo key = new Foo();
        map.put(key, "1");

        //when
        key = null;
        System.gc();

        //then
        assertAll(
                "WeakHashMap 은 참조를 끊으면 map 이 비어있다.",
                () -> assertThat(map.isEmpty()).isTrue()
        );
    }

image

HashMap의 경우 key 를 null 처리후 GC를 실행시켜도 인스턴스가 Map에 그대로 남아 있는것을 확인 할 수 있었다.

    public static void main(String[] args) {
        Map<Foo, String> map = new HashMap<>();

        Foo key = new Foo();
        map.put(key, "1");

        key = null;
        System.gc();

        Scanner sc = new Scanner(System.in);
        sc.nextLine();
    }

입력 대기 상태에서 jcmd를 통해 확인한 결과.

image