티스토리 뷰

자바의 가비지 컬렉션

 C, C++ 과 같이 메모리를 직접 관리해야 하는 언어와 달리, 자바는 가비지 컬렉션을 지원한다. 자바의 가비지 컬렉션은 기본적으로 참조를 기반으로 한다. 객체 인스턴스의 쓰임새를 판단해 쓰임이 다 했다고 판단되는 자원을 정리하는 원리이다. 개발자는 메모리를 직접 관리하지 않아도 되지만 적어도 객체의 쓰임이 끝났다는 것을 표현해 주어야 한다. 그렇지 않으면 개발자가 인지하지 못하는 메모리 누수가 발생하여 프로그램의 예기치 못한 종료를 야기할 수 있다.

객체 참조를 해제하는 법

 객체 참조를 해제하는 가장 단순한 방법은 참조변수에 null 을 할당하는 것이다. 피참조 지정을 잃은 인스턴스는 쓰임새가 다했다는 판단의 범위로 들어가게 된다. 하지만 이 단순한 방법은 예외적인 경우에 활용해야 한다. 모든 객체를 다 쓰자마자 일일히 null 처리하는 코드는 결국 메모리를 직접 관리하는 코드와 같다.

 

 다 쓴 참조를 해제하는 가장 좋은 방법은 그 참조를 담은 변수를 유효 범위(scope) 밖으로 밀어내는 것이다. 변수를 밀어낸다 라는 표현이 어색할 수 있다. 풀어서 작성해보면 변수를 정의할 때 이 변수의 사용범위가 어디까지가 될 지 생각해서 정의해보자 가 되겠다. 일반적인 지역변수, 인스턴스 내부에서 사용되는 전역변수 들은 지역 스코프의 종료, 인스턴스가 사용된 스코프의 종료와 함께 가비지 컬렉팅의 대상이 된다,

 

 null 처리는 자기 메모리를 직접 관리하는 클래스에서 필요하다. Stack 과 같이 내부에서 배열의 인스턴스와 참조 포인터를 운영하는 클래스는 내부 메모리 관리가 필요하다. 아래와 같이 Stack 클래스의 pop 메서드는 상위 클래스인 Vector 의 removeElementAt 메서드를 통해 내부 메모리 해제를 명시적으로 수행한다.

    public synchronized E pop() {
        E       obj;
        int     len = size();

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    }
    public synchronized void removeElementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = elementCount - index - 1;
        if (j > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        modCount++;
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }

메모리 누수원인

 캐시 또한 메모리 누수를 일으킨다. 객체 참조를 캐시에 넣고나서 해제해주지 않으면 누수가 발생할 수 있다. 캐시를 설계할 때는 캐싱 자원의 유효기간을 염두해야 한다. 유효기간을 정확히 정의하기 어렵다면 주기적인 캐시 청소방안을 설계해 주는 것이 좋다.

 

 리스너 혹은 콜백도 메모리 누수를 일으킬 수 있다. 클라이언트가 콜백을 등록만 하고 해지하지 않으면 실행되지 못한 콜백이 지속적으로 쌓일 수 있다.

정리

 실무에서 객체 참조 해제에 대해 깊숙히 고민해 본 적이 많지 않은 것 같다. 최근에는 더 견고한 프로그램을 설계하기 위해 임의의 자료구조나 캐시를 설계하는 경우가 생기고 있다. 메모리를 다루는 설계를 적용할 때에는 인스턴스 해제를 고려해야겠다는 생각이 든다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday