728x90
다 쓴 객체 참조를 해제하라
C나 C++의 경우 개발자가 직접 메모리 관리를 해야한다.
하지만 JAVA의 경우 가비지 컬렉터가 있어서 메모리를 관리해준다.
그래도 신경을 써야한다.
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 object) {
ensureCapacity();
elements[size++] = object;
}
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
return elements[--size];
}
/**
* 원소를 위한 공간을 적어도 하나 이상 확보한다.
* 배열 크기를 늘려야 할 때 마다 대략 2 배씩 늘린다.
*/
private void ensureCapacity() {
if (elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
위 코드의 경우 메모리 누수 문제가 있다.
pop을 할 때 --size를 인덱스로 가져가면서 객체를 꺼내지만 그 객체는 가비지 컬렉터가 회수하지 않는다.
결국 이런 객체들이 남게 되고, 메모리 누수가 발생해서 성능이 저하된다.
public Object pop()
{
if (size == 0)
{
throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null; // 다 쓴 참조 해제
return result;
}
이렇게 하면 객체를 pop하고 null로 처리하기 때문에 참조가 해제된다.
다른 메모리 누수 원인
1. 캐시
객체 참조를 캐시에 넣어놓고 까맣게 잊으면, 메모리 누수의 범인이 된다.
해결법
WeakedHashMap 사용
Key를 참조하는 동안(value가 아니다)만 엔트리가 살아있는 캐시가 필요한 상황이면 WeakHashMap을 활용할 수 있다.
혹은 백그라운드 스레드에서 사용하지 않는 엔트리를 청소해주거나, 새 엔트리를 추가할 때 부수작업으로 수행할 수 도 있다.
2. Listener / Callback
클라이언트가 콜백을 등록만 하고 명확히 해지하지 않으면 콜백은 계속해서 쌓여간다.
해결법
WeakedHashMap 사용
이 때 콜백을 약한 참조로 등록해 두면 가비지 컬렉터터가 즉시 수거해가는데, WeakHashMap의 key로 저장하는 식이다.
728x90
'EFFECTIVE JAVA' 카테고리의 다른 글
EFFECTIVE JAVA TIL 10 - 모든 객체의 공통 메서드 / 아이템 10 (0) | 2024.08.02 |
---|---|
EFFECTIVE JAVA TIL 08 - 객체 생성과 파괴 / 아이템 8 (2) | 2024.07.25 |
EFFECTIVE JAVA TIL 06 - 객체 생성과 파괴 / 아이템 6 (0) | 2024.07.25 |
EFFECTIVE JAVA TIL 05 - 객체 생성과 파괴 / 아이템 5 (0) | 2024.07.25 |
EFFECTIVE JAVA TIL 04 - 객체 생성과 파괴 / 아이템 4 (0) | 2024.07.24 |