[Effetive-Java] Item7 - 다 쓴 객체 참조를 해제하라

imcool2551·2022년 2월 16일
0

Effective-Java

목록 보기
7/8

1. 메모리 누수


C, C++ 처럼 메모리를 직접 관리해야 하는 언어를 사용하다가 자바를 사용하면 다 쓴 객체를 알아서 회수해가는 가비지 콜렉션이 매우 편리하게 느껴진다. 그렇다고 메모리 관리를 아예 신경쓰면 안 된다는 것은 아니다. 자바에서도 잘못된 코드로 메모리 누수가 일어날 수 있다. 메모리 누수가 심한경우 OutOfMemoryError를 일으켜 프로그램이 종료될 수 있다.

2. 스택 예시


package chapter2.item7;

import java.util.Arrays;
import java.util.EmptyStackException;

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

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

  	// 메모리 누수!
    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() 메소드 구현을 보자. 스택의 pop으로 반환한 객체는 더 이상 사용될 일이 없으므로 참조를 해제해야 한다. 그러나 위의 구현은 스택배열이 객체의 다 쓴 참조(obsolete reference)를 가지고 있으므로 객체가 가비지 콜렉션의 대상이 되지 않는다. 더 나쁜것은 그 객체가 참조하는 모든 객체또한 마찬가지로 가비지 콜렉션 되지 않는다는 사실이다. 이는 성능에 악영향을 줄 수 있다.

3. 참조 해제하기


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

위처럼 다 쓴 참조를 null처리해주기만 하면 해당 객체를 접근할 방법이 없기 때문에 가비지 콜렉션의 대상이 된다. 혹시 프로그래머가 스택에 더 이상 존재하지 않는 객체에 접근하려 해도 NPE가 발생한다. 일반적인 경우 모든 객체를 사용한 뒤 null처리할 필요는 없다. 객체 참조를 null처리 하는 경우는 예외적인 경우여야 한다. Stack 클래스는 자신의 메모리를 직접 관리하는 특수한 클래스다. elements 배열과 size 변수를 통해 활성객체와 비활성객체를 직접 관리한다. 문제는 가비지 컬렉터가 활성객체와 비활성객체를 구분할 길이 없다는 것이다. 그러므로 프로그래머가 비활성객체는 직접 null처리 해줘야 한다.

profile
아임쿨

1개의 댓글

comment-user-thumbnail
2022년 2월 28일

안녕하세요 ~

답글 달기