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

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

메모리 누수 원인

1) 다 쓴 객체 참조 유지

  • 사용되지 않는 객체 참조 하나를 살려둘 경우, 해당 객체를 참조하는 모든 객체들이 연달아 회수되지 못한다.

  • 아래는 스택에서 꺼낸 더이상 사용하지 않는 객체를 가비지 컬렉터가 회수하지 않아 메모리 누수가 발생하는 코드이다.

public Object pop() {
	if (size == 0)
		throw new EmptyStackException();
	return elements[--size];
}
  • 메모리 누수를 막기 위해 스택에서 꺼내어 더이상 사용하지 않는 객체를 null 처리하여 참조 해제한다.

  • 직접 자기 메모리를 관리하는 클래스의 경우 원소를 다 사용한 즉시 원소가 참조한 객체들을 null 처리해야 한다.

public Object pop() {
	if (size == 0)
		throw new EmptyStackException();
	Object result = elements[--size];
    element[size] = null;
    return result;
}
  • 참조를 담은 변수를 유효 범위 밖으로 밀어내는 것이 다 쓴 참조를 해제하는 가장 좋은 방법

  • 변수의 범위를 최소가 되게 정의하면 된다. (item57)

2) 캐시

  • 객체 참조를 캐시에 넣고, 객체를 다 쓴 후 내버려두는 경우 메모리 누수 발생

  • WeakHashMap

    • 캐시 외부에서 키를 참조하는 동안만 엔트리가 살아있는 캐시가 필요한 상황일 때, 외부에서 다 쓴 엔터리를 자동 제거해준다.

  • LinkedHashMap

    • removeEldestEntry() 메서드를 사용해 캐시에 새 엔트리 추가 시 부수 작업으로 시간이 지날수록 엔트리의 가치를 떨어뜨린다.

3) 리스너, 콜백

  • 클라이언트가 콜백을 등록만 하고 명확히 해지하지 않을 경우 계속 쌓일 수 있다.

  • 콜백을 약한 참조로 저장하면 가비지 컬렉터가 즉시 수거해가 누수를 막을 수 있다.

Last updated