# Item 7. 다 쓴 객체 참조를 해제하라

## 메모리 누수(Memory Leak)

* C, C++과 같은 low level 언어와 달리 Java는 가비지 컬렉터가 참조되지 않는 객체를 알아서 회수(메모리에서 제거)하기 때문에 프로그래머가 명시적으로 객체를 방출할 필요가 없음
* 하지만, 실제로 앞으로 사용될 일이 없음에도 가비지 컬렉터가 회수하지 않는 객체들이 존재하게 될 수 있고, 이를 `메모리 누수` 라고 함
* 이는 논리적으로 호출될 일이 없음에도 해당 객체들의 참조를 여전히 가지고 있기 때문에 발생하는 문제
* 이러한 사례를 예방하기 위해서는 다 쓴 참조를 null처리할 필요가 있음
  * 하지만 매 객체를 미사용 순간마다 null로 처리하는 일은 코드를 필요 이상으로 지저분하게 만듦
  * 그렇다면 어떨 때 명시적 null 처리를 수행해야 할까?

## 메모리 누수 사례와 해결 방법

### 자기 자신의 메모리를 직접 관리하는 클래스

* Stack, Queue와 같은 Data Structure의 구현체가 이에 해당
* 이 경우 원소를 제거할 때(pop, deque 등) 명시적으로 해당 객체에 대한 자료구조 클래스의 참조를 null처리해 주는 것이 좋음

### 캐시

* In-memory 캐시에 저장한 뒤, 해당 캐시가 사용되지 않음에도 해당 캐시에 대한 참조가 존재하면 이또한 메모리 누수에 해당
* 캐시 키에 대한 참조가 유지되는 동안 캐시가 유효하도록 구현할 수 있다면, `WeakHashMap`을 사용함으로써 이러한 누수를 예방할 수 있음
  * `WeakHashMap`이란, key에 대한 참조가 사라지면 해당 entry를 제거하는 Map 구현체
* 아니면 백그라운드에서 동작하는 스레드를 통해 캐시 사용 여부를 체크하거나, 직접 방출 알고리즘을 적용할 수도 있음
  * 예시: LinkedHashMap으로 구현한 후 새 데이터가 추가될 때 지정된 MAX\_SIZE를 넘었다면 removeEldestEntry를 통해 가장 오래된 데이터를 방출 (LRU)

### 리스너(Listener), 콜백(Callback)

* 리스너, 콜백은 클라이언트가 등록 후 명시적으로 해지해야 메모리에서 방출됨
* 즉, 별도 조치가 없으면 메모리에 계속 쌓이게 됨 (메모리 누수)
* 이를 예방하기 위해서는 이들을 `약한 참조(weak reference)`로 저장해야 함
  * 이를 위해 `WeakHashMap`을 사용할 수 있음

## 가장 좋은 메모리 관리 방법

* 명시적 null처리를 하기보다는, 변수를 최소한의 scope에 포함되도록 정의해 scope가 끝날 때 해당 scope 내에서 사용된 변수들이 가비지 컬렉터에 의해 자동으로 회수되도록 하는 것

## Reference

* <https://blog.breakingthat.com/2018/08/26/java-collection-map-weakhashmap/>
