'GC를 갖춘 언어를 사용하면 편리하지만, 메모리 관리에 더 이상 신경쓰지 않아도 되는 것은 아니다.'
메모리 누수 (memory leak)
- 프로그램이 필요하지 않은 메모리를 계속 점유하고 있는 현상
- 할당된 메모리를 사용 후 반환하지 않는 것이 누적되면 메모리가 낭비된다.
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);
}
}
}
>- 다 쓴 참조(obsolete reference : 앞으로 다시 쓰지 않을 참조를 의미
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // 다 쓴 참조 해제
return result
}
// Vector 클래스의 removeElementAt
public synchronized void removeElementAt(int index) {
...
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
@Test
void weakHashMapTest() {
weakHashMap<Integer, String> map = new weakHashMap<>();
Integer key1 = 1000;
Integer key2 = 2000;
map.put(key1, "Orange");
map.put(key2, "Coffee");
key1 = null;
System.gc();
map.entrySet().stream.forEach(e1 -> System.out.println(e1));
assertThat(map.size()).isEqualTo(1);
}
메모리 누수는 확인하기 쉽지 않나 오랫동안 잠복하는 경우가 있다.
메모리 누수가 일어나는 패턴들을 알아두고 대처 방법을 익혀두는 것이 매우 중요하다.