본문 바로가기

Languages/Java

WeakHashMap과 약한 참조

WeakHashMap의 특징

약한 참조

WeekHashMap은 키에 대한 약한 참조를 저장한다.

키 객체에 대한 다른 참조가 없다면 Garbage Collector에 의해 수거된다.

키 객체가 Garbage Collector에 의해 수거되면 해당 키와 연관된 엔트리도 자동으로 제거된다.

→ 메모리 누수를 방지할 수 있다.

동기화 x

동기화를 지원하지 않는다.

여러 스레드에서 동시에 WeakHashMap을 사용하려면 외부에서 동기화 처리를 해야한다.

Null 허용

key와 value에서 모두 null을 허용한다.

null 키는 약한 참조가 아니기 때문에 GarbageCollecor에 의해 수거되지 않는다.

WeakHashMap 키에 대한 참조 없을 때 GC에 의해 수거되는지 확인

import java.util.WeakHashMap;

public class WeakHashMapTest {

    public static void main(String[] args) {
        WeakHashMap<Name, Integer> map = new WeakHashMap<>();
        map.put(new Name("YEEUN"), 5);
        System.gc();
        while(!map.isEmpty()){}
        System.out.println(map.isEmpty());
    }
}

class Name {
    String name;

    public Name(String name) {
        this.name = name;
    }
}

참조 (Reference)

java.lang.ref 패키지에 여러 참조 유형을 제공한다.

각 참조 유형은 객체가 언제 가비지 컬렉션의 대상이 될 수 있는지 결정한다.

강한 참조 (Strong Reference)

Object obj = new Object();
  • 변수가 객체를 직접 참조할 때 사용된다.
  • 가비지 컬렉션의 대상이 되지 않는다.

소프트 참조 (Soft Reference)

SoftReference<Object> softReference = new SoftReference<>(new Object());
  • SoftReference 클래스를 사용해 만들어진다.
  • 메모리가 부족할 때 가비지 컬렉터에 의해 회수된다.

약한 참조 (Weak Reference)

WeakReference<Object> weakReference = new WeakReference<>(new Object());
  • WeakReference 클래스를 사용해 만들어진다.
  • 가비지 컬렉션 시점에 항상 회수된다.

팬텀 참조 (Phantom Reference)

ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomReference = new PhantomReference<>(new Object(), queue);
  • PhantomReference 클래스를 사용하여 만들어진다.
  • 객체가 메모리에서 회수되기 전에 특정 작업을 수행하려는 경우에 사용된다.
  • PhantomReference 로 참조된 객체를 직접 가져올 수 없다.
    • get()을 사용해도 항상 null을 반환한다.
  • ReferenceQueue에 추가되면, 객체가 메모리에서 회수될 준비가 되었음을 알 수 있다.
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;

public class PhantomReferenceExample {

    public static void main(String[] args) throws InterruptedException {
        // 참조 큐 생성
        ReferenceQueue<String> queue = new ReferenceQueue<>();

        // 객체 생성
        String hello = new String("Hello");

        // 객체에 대한 팬텀 참조 생성
        PhantomReference<String> phantomHello = new PhantomReference<>(hello, queue);

        // 강한 참조 삭제
        hello = null;

        // 가비지 컬렉터 실행
        System.gc();

        // 잠시 기다림
        Thread.sleep(1000);

        // 참조 큐로부터 팬텀 참조 확인
        Reference<? extends String> referenceFromQueue = queue.poll();
        if (referenceFromQueue != null) {
            System.out.println("Phantom reference is enqueued after GC");
        }
    }
}

'Languages > Java' 카테고리의 다른 글

리플렉션의 InvocationTargetException  (0) 2023.11.08
예외처리  (0) 2023.05.24
Primitive Type, Reference Type  (0) 2023.04.25
JVM과 GC  (0) 2023.04.12
[Java] HashMap, HashTable, HashSet  (0) 2023.04.12