아이템 6. 유효기간이 지난 객체 참조는 폐기하라.

06. 유효기간이 지난 객체 참조는 폐기하라.

public class Stack{
	Object[] elements;
	int size = 0;
	static final int DEFAULT_INITAL_CAPACITY = 16;
	
	public Stack(){
		elements = new Object[DEFAULT_INITAL_CAPACITY];
	}
	
	public void push(Object e){
		ensureCapacity();
		elements[size++] = e;
	}
	
	public Object pop(){
		if(0 >= size){
			throw new EmptyStackException();
		}
		return elements[--size];
	}
	
	/**
	 * 적어도 하나 이상의 원소를 담을 공산을 보장한다.
	 * 배열의 길이를 늘려야 할 때마다 대략 두배씩 늘인다. 
	 */
	private void ensureCapacity(){
		if( elements.length == size ){
			element = Arrays.copyOf(eleemnts, (2 * size) + 1);
		}
	}
	
}

위의 코드는 정상적으로 동작한다. 하지만, pop 메소드를 호출하여 클라이언트 코드에서 소비해도 elements의 객체를 계속 참조 하고 있기 때문에, 메모리 누수가 발생한다. 이런 현상을 의도치 않은 객체 보유(uniterntional object retention)이라고 한다.

	public Object pop(){
		if(0 >= size){
			throw new EmptyStackException();
		}
		Object result = elements[--size];
		elements[size] = null; // 만기된 객체에 대한 참조 제거
		return result;
	}

위와 같이 elements에 만기된 객체에 대해서 null를 할당하여 GC의 제거 대상이 될수 있도록 한다.

이런 오류를 한번 접하고 나면, 객체 사용이 끝나면 즉시 그 참조를 null 처리해야 한다는 강박관념에 사로잡히는 경우가 있다. 하지만 그럴 필요도 없고, 바람직하지도 않다. 객체 참조를 null 처리 하는 것은 규범(norm)이라기보단 예외적인 조치가 되어야 한다. 만기 참조를 제거하는 가장 좋은 방법은 해당 참조가 보관된 변수가 유효범위(scope)를 벗어나게 두는 것이다. 변수를 정의할 때 유효범위를 최대한 좁게 만들면 자연스럽게 해결된다.