JAVA 는 가비지컬렉터가 다 쓴 객체를 알아서 회수해 간다.
다만 코드 작성시 메모리 누수가 발생할 수 있다.
예제 코드에서는 스택을 직접 구현 한뒤 POP() 메소드를 호출할 때를 예로 들고 있다
- 예제 코드
=================================================================================================================
public Object pop(){
if(size ==){
throw new EmptyStackException();
}
return elements[--size]; //해당 값을 리턴해주고 인덱스를 줄임으로, 더이상 해당 인덱스에 있는 값은 사용하지 않지만
//아직 참조중이므로 가비지 컬렉션에서는 회수해 가지 않음
}
=================================================================================================================
위 메소드에서 statck 에 담겨있던 객체들은 pop() 메소드 호출로 꺼내져 사용이 다 끝난 뒤지만
elements에서는 해당 객체의 참조를 해제하지 않았기 때문에 가비지렉션은 해당 값을 회수해 가지 못한다.
elements의 활성 영역은 size 의 값보다 작은 값들로 구성되어 있다.
해당 값보다 큰 인덱스에 있는 값들은 더이상 사용할 순 없지만 참조를하고있다.
이러한 것을 다 쓴 참조(obsolete reference) 라고 한다.
이러한 것을 예방하기 위해서 다쓴 참조들은 null 로 참조를 해제 해야한다
- 올바른 pop 메소드
=================================================================================================================
public Object pop(){
if(size==0){
throw new EmptyStackException();
}
Object result = elements[--size];;
elements[size] =null; //다쓴 객체 참조 해제
return result;
}
=================================================================================================================
다 쓴 참조를 null 처리하면 다른 이점도 따라오며
만약 null 처리한 참조를 실수로사용하려 하면 프로그램은 즉시 NullPointerException을 던지며 종료한다.
다만 모든 객체를 다 쓴 후 null 을 넣으라는것이 아니고 객체를 참조 해제 하는 일은 예외적인 경우에만 해야 한다.
일반적으로 자기 메모리를 직접 관리하는 클래스라면 프로그래머는 항시 메모리 누수에 주의해야 한다.
캐시 역시 메모리 누수를 일으키는 주범이다.
또한 리스너 혹은 콜백이라 부르는 것들도 메모리 누수를 일으킨다.
메모리 누수는 겉으로잘 드러나지 않아 시스템에 수년간 잠복하는 사례도 있다.
이런 누수는 철저한 코드 리뷰나 힙 프로파일러 같은 디버깅 도구를 동원해야만 발견되기도 한다.
그래서 이런 종류의 문제는 예방법을 익혀두는 것이 매우 중요하다.