Java ‐ 다 쓴 객체 참조를 해제하라[Effective Java Item 7] - dnwls16071/Backend_Summary GitHub Wiki

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

// Bad
public class Stack {
	private static final int DEFAULT_INITAL_CAPACITY = 16;

	private Obejct[] elements;
	private int size = 0;
	
	public Stack() {
		elements = new Object[DEFAULT_INITAL_CAPACITY];
	}

	public void push(Object e) {
		ensureCapacity();
		elements[size++];
	}

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

	private void ensureCapacity() {
		if (elements.length == size) {
			elements = Arrays.copyOf(elements, 2 * size + 1);
		}
}
  • pop() 메서드를 호출하면 실제 값은 삭제되지 않고 인덱스만 한칸씩 이동하는 것으로 메모리 누수가 발생하게 된다.
// Good
public Object pop() {
	if (size == 0) {
		return new EmptyStackException();
	}
	Object result = elements[--size];
	elements[size] = null;  // 다 쓴 객체의 참조를 null로 해제한다.
	return result;
}
  • 다 쓴 참조를 null 처리하면 다른 이점도 따라온다.
  • 만약 null 처리한 참조를 실수로 사용하게 되면 프로그램은 즉시 NPE를 던지며 종료된다.
  • 지역 변수로 선언된 컬렉션 타입은 메서드가 끝나면(=스코프에서 벗어나면) 더 이상 참조가 없기에 GC의 대상이 된다. 따라서 일반적으로 메서드가 종료되면 메모리가 해제된다.
  • 반대로 그 컬렉션 타입이 static으로 선언되어 참조가 유지되면 GC가 회수되지 못해 메모리가 유지되어 잠재적 메모리 누수가 발생하게 된다.