[07] 다 쓴 객체 참조를 해제하라
핵심 내용
'GC 믿고 메모리 누수 신경 안쓰면 안된다.' 가 핵심 내용이다. 사실 이 아이템은 메모리 누수의 개념을 알고, 어떤 경우에 메모리 누수가 잘 발생하는지에 대해서 이해하는 내용이 전부다.
메모리 누수는 어떨 때 주로 일어날까
책의 표현으로 '자기 메모리를 직접 관리하는 클래스라면 프로그래머는 항시 메모리 누수에 주의해야 한다' 라고 말하고 있다. 책의 예시 코드로는 자바에서 제공해주는 Stack 을 안쓰고 직접 만든 Stack 에 데이터를 넣고 빼는데, pop 을 시킬때 해당 엘리먼트를 null 처리를 해주지 않는 방식으로 메모리 누수를 야기시킨다.
아래 코드는 책의 예시 코드이다.
약간 의아스러웠던 것이 있는데, 이게 다시 push 가 되면 어차피 덮어 씌여서 결과적으로 메모리 누수가 아닌거 같은데 왜 메모리 누수라는거지 라고 생각했었는데 책에서 이 부분에 대해서 별달리 말이 없다.
그래서 GPT 한테 물어보니 내 생각이 맞다고 일단 추측할 수 있었다. 책에서 말하는 메모리 누수는 pop() 이 된 그 상태만을 의미한다. 즉, a,b 둘을 넣고 pop() 을 두 번 하면 size(=여기서는 인덱스라는 변수명이 더 맞는 것 같은데 일단 책 그대로 구현했다)가 줄어드니까 결과적으로 a, b 는 메모리 상에 존재는 하지만 사실상 사용되지 않는 객체라서 이 스냅샷 상태가 '메모리 누수'가 된 상태라고도 할 수 있는 것이다.
위 문제를 개선하려면 어떻게 해야할까?
누수를 막으면 된다. 누수시키는 핵심 원인을 명시적으로 메모리를 반환시킨다.
메모리 누수의 주요 범인 셋(책에서 언급하고 있는)
위에서 코드로 묘사한 자기 메모리를 직접 관리하는 클래스
코드로 직접 구현 했으니 설명 생략한다.
캐시 메모리
이건 커스텀하게 뭔가 캐시 풀을 직접 만들때를 이야기 하는 것 같다. 캐시가 메모리 누수를 일으킨다는 저자의 논리의 근거는 쓰고 계속 살려뒀을때를 이야기한다. 그런데 레디스나 헤이즐캐스트 같이 서드파티 캐시를 사용하면 TTL 을 설정해주면 알아서 캐시가 죽어서 메모리가 반환된다(내부적으로 그렇게 구현되어 있을 것이다)
리스너 또는 콜백
리스너 또는 콜백이 왜 메모리 누수와 관련이 있다는 건지 좀 이해가 안갔다. 결론적으로 리스너든 콜백이든 이를 실행시키는 객체가 리스너 또는 콜백에 대한 참조값을 가지고 있어야 하고, 리스너 또는 콜백이 호출 되고 나서는 이 참조값이 필요가 없는데 메모리가 반환되지 않고 계속 가지고 있는 상태 자체가 '메모리 누수' 라는 의미로 보인다.
Last updated