일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- junit 5
- 접근지시자
- annotation processor
- 항해99
- 함수형 인터페이스
- 람다식
- raw 타입
- 로컬 클래스
- auto.create.topics.enable
- 제네릭 와일드 카드
- 제네릭 타입
- yield
- docker
- throwable
- 브릿지 메소드
- 프리미티브 타입
- 바운디드 타입
- System.in
- 자바스터디
- 자바할래
- Study Halle
- System.err
- System.out
- Switch Expressions
- 익명 클래스
- 정렬
- 합병 정렬
- 상속
- 스파르타코딩클럽
- github api
- Today
- Total
코딩하는 털보
이펙티브 자바, 아이템 7. 다 쓴 객체 참조를 해제하라 본문
이펙티브 자바, 아이템 7. 다 쓴 객체 참조를 해제하라
자바의 가비지 컬렉터는 다 쓴 객체를 알아서 회수해가지만 그렇다고 메모리 관리에 더 이상 신경 쓰지 않아도 되는 것은 아니다.
가비지 컬렉션 언어에서는 메모리 누수를 찾기가 아주 까다롭다. 객체 참조 하나를 살려두면 가비지 컬렉터는 그 객체뿐아니라 그 객체가 참조하는 모든 객체를 회수해가지 못한다. 그래서 단 몇 개의 객체가 매우 많은 객체를 회수되지 못하게 할 수 있고 잠재적으로 성능에 악영향을 줄 수 있다.
해법은 참조해제. 해당 참조를 다 썼을 때 null 처리하면 된다.
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
Object result = elements[--size];
elements[--size] = null; // 다 쓴 객체 참조 해제
return result;
}
객체 참조를 null 처리하는 일은 스택처럼 자기 메모리를 직접 관리하는 클래스에서 처럼 예외적인 경우여야 한다. 참조 해제의 가장 좋은 방법은 그 참조를 담은 변수를 유효 범위 밖으로 밀어내는 것이다.
캐시
캐시 역시 메모리 누수를 일으키는 주범이다.
캐시 외부에서 키를 참조하는 동안만 엔트리가 살아 있는 캐시가 필요한 상황이라면 WeakHashMap를 사용해 캐시를 만들자. 다 쓴 엔트리는 자동으로 제거된다.
보통 캐시 엔트리의 유효 기간을 정의하기 어려우므로 시간이 지날수록 엔트리의 가치를 떨어뜨리는 방식을 사용한다. 이런 방식에서는 쓰지 않는 엔트리를 이따금 청소해줘야 하는데, 백그라운드 스레드를 활용하거나 새 엔트리를 추가할 때 부수 작업으로 수행하는 방법(예를 들어 LinkedHashMap의 removeEldestEntry 메서드)이 있다.리스너 혹은 콜백
클라이언트가 콜백을 등록만 하고 명확히 해지하지 않는다면 콜백은 계속 쌓여갈 것이다. 이럴 때 콜백을 약한 참조로 저장하면 가비지 컬렉터가 즉시 수거해간다. 예를들어 WeakHashMap에 키로 저장하면 된다.핵심 정리
메모리 누수는 찾기 어려우므로 예방법을 익혀두는 것이 매우 중요하다.