> For the complete documentation index, see [llms.txt](https://develop-footprint.gitbook.io/o/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://develop-footprint.gitbook.io/o/java/effective-java/2/item7.md).

# item7) 다 쓴 객체는 참조 해제하라

* 메모리 누수가 발생하면 점차 가비지 컬렉션 활동과 메모리 사용량이 늘어나 성능 저하가 발생할 수 있고, 심하면 디스크 페이징이나 OutOfMemoryError가 발생해 프로그램이 종료될 수 있다.

## **메모리 누수 원인**&#x20;

### **1) 다 쓴 객체 참조 유지**

* 사용되지 않는 객체 참조 하나를 살려둘 경우, 해당 객체를 참조하는 모든 객체들이 연달아 회수되지 못한다.
* 아래는 스택에서 꺼낸 더이상 사용하지 않는 객체를 가비지 컬렉터가 회수하지 않아 메모리 누수가 발생하는 코드이다.

```java
public Object pop() {
	if (size == 0)
		throw new EmptyStackException();
	return elements[--size];
}
```

* 메모리 누수를 막기 위해 스택에서 꺼내어 더이상 사용하지 않는 객체를 null 처리하여 참조 해제한다.
* 직접 자기 메모리를 관리하는 클래스의 경우 원소를 다 사용한 즉시 원소가 참조한 객체들을 null 처리해야 한다.

```java
public Object pop() {
	if (size == 0)
		throw new EmptyStackException();
	Object result = elements[--size];
    element[size] = null;
    return result;
}
```

* 참조를 담은 변수를 유효 범위 밖으로 밀어내는 것이 다 쓴 참조를 해제하는 가장 좋은 방법
* 변수의 범위를 최소가 되게 정의하면 된다. (item57)

### **2) 캐시**

* 객체 참조를 캐시에 넣고, 객체를 다 쓴 후 내버려두는 경우 메모리 누수 발생
* WeakHashMap
  * 캐시 외부에서 키를 참조하는 동안만 엔트리가 살아있는 캐시가 필요한 상황일 때, 외부에서 다 쓴 엔터리를 자동 제거해준다.
* LinkedHashMap
  * removeEldestEntry() 메서드를 사용해 캐시에 새 엔트리 추가 시 부수 작업으로 시간이 지날수록 엔트리의 가치를 떨어뜨린다.

### **3) 리스너, 콜백**

* 클라이언트가 콜백을 등록만 하고 명확히 해지하지 않을 경우 계속 쌓일 수 있다.
* 콜백을 약한 참조로 저장하면 가비지 컬렉터가 즉시 수거해가 누수를 막을 수 있다.
