전공공부
아이템 7. 다 쓴 객체 참조를 해제하라 본문
자바는 Managed Language로써 일반적으로 언어상에서 메모리를 관리해주는 언어이다. 그래서, 메모리를 직접 관리하지 않아도 된다고 착각 할 수 있는데 이는 사실이 아니다.
예시 코드
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();
}
private void ensureCapacity(){
if(elements.length == size)
elements = Arrays.copyOf(elements,2*size+1);
}
}
해당 코드는 실제 사용시 별 문제 없이 돌아 갈 것 처럼 보인다.
하지만, 이 코드는 메모리 누수가 존재한다.
스텍이 다 쓴 참조 객체의 메모리를 소유하고 있기 때문이다.
그래서 이를 방지 하기 위해서는 다 쓴 참조 객체를 null로 다시 초기화 진행 시켜주면된다.
public Object pop(){
if(size == 0)
throw new EmptyStackException();
Object res = elements[--size];
elements[--size] = null; // 다 쓴 참조객체 null 처리
return res;
}
그러나, 위와 같은 상황은 예외적인 상황에서만 사용되어지고 또 다른 좋은 방법은 유효 범위(scope) 바깥으로 참조 객체를 밀어내는 것이다.
public void test(){
Object test = 24;
}
위와 같이 코드를 짜게 된다면 지역 변수 scope 내부에서만 test 변수가 유효하니 GC에서 알아서 메모리 관리를 해준다.
메모리 관리에 유의 해야 할 지점
위 Stack 클래스 처럼 가비지 컬랙터가 사용 종료 여부를 알 수 없고 메모리를 직접 관리하는 클래스이면 사용자가 직접 메모리 누수를 관리하여야 한다.
캐시 = 메모리 누수의 주요 원인
객체 참조를 캐시에 나두고서 그 객체를 다 쓴 이후에도 한참을 그냥 놔두게 된다면 이 또한 메모리 누스의 원인이다.
그러므로 캐시 외부에서 key를 통해서 살아 있는 동안만 엔트리가 살아 있는 캐시가 필요하다면 WeakHashMap을 사용하자
WeakHashMap의 이해
WeakHashMap을 이해하고 넘어가려면 아래 개념을 먼저 파악하여야 한다.
- 강한 참조 (Strong Reference)
Integer prime = 1; 와 같은 가장 일반적인 참조 유형이다. prime 변수 는 값이 1 인 Integer 객체에 대한 강한 참조를가진다. 이 객체를 가리키는 강한 참조가 있는 객체는 GC대상이 되지않는다. - 부드러운 참조 (Soft Reference)
SoftReference<Integer> soft = new SoftReference<Integer>(prime); 와 같이 SoftReference Class를 이용하여 생성 가능하다. 만약 prime == null 상태가 되어 더이상 원본(최초 생성 시점에 이용 대상이 되었던 Strong Reference) 은 없고 대상을 참조하는 객체가 SoftReference만 존재할 경우 GC대상으로 들어가도록 JVM은 동작한다. 다만 WeakReference 와의 차이점은 메모리가 부족하지 않으면 굳이 GC하지 않는 점이다. - 약한 참조 (Weak Reference)
WeakReference<Integer> soft = new WeakReference<Integer>(prime); 와 같이 WeakReference Class를 이용하여 생성이 가능하다. prime == null 되면 (해당 객체를 가리키는 참조가 WeakReference 뿐일 경우) GC 대상이 된다. 앞서 이야기 한 내용과 같이 SoftReference와 차이점은 메모리가 부족하지 않더라도 GC 대상이 된다는 것이다. 다음 GC가 발생하는 시점에 무조건 없어진다.

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
public class WeakHashMapTest {
public static void main(String[] args) {
WeakHashMap<Integer, String> map = new WeakHashMap<>();
Map <Integer,String> map1 = new HashMap();
Integer key1 = 1000;
Integer key2 = 2000;
map1.put(key1,"k");
map1.put(key2,"a");
SoftReference softReference = new SoftReference<Map>(map1);
map.put(key1, "test a");
map.put(key2, "test b");
key1 = null;
System.gc(); //강제 Garbage Collection
System.out.println(softReference.get());
map1 = null;
softReference = null;
System.gc();
map.entrySet().stream().forEach(el -> System.out.println(el));
}
}

결론
메모리 누수는 겉으로 드러나지 않아 시스템에 잠복하기 쉬워 발견하기 힘들다. 따라서 예방법을 숙지하고 상황에 맞게 잘 쓰자.
'Study > Java' 카테고리의 다른 글
아이템 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라 (0) | 2023.03.05 |
---|---|
아이템 13. clone 재정의는 주의해서 진행해라 (2) | 2023.02.20 |
아이템 2. 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2023.01.31 |
아이템 61. 박싱된 기본 타입보다는 기본 타입을 사용하라 (0) | 2023.01.24 |
아이템 60. 정확한 답이 필요하다면 float와 double형의 사용을 피하라 (0) | 2023.01.15 |