1. 개요
이 기사에서는 Java 언어에서 약한 참조의 개념을 살펴보겠습니다.
우리는 이것들이 무엇인지, 그것들이 무엇을 위해 사용되는지, 그것들을 적절하게 사용하는 방법을 설명할 것입니다.
2. 약한 참조
약하게 참조된 개체는 약하게 도달할 수 있을 때 가비지 수집기에 의해 지워집니다.
약한 도달 가능성은 객체 에 자신을 가리키는 강한 참조나 부드러운 참조가 없음을 의미합니다 . 개체는 약한 참조를 통과해야만 도달할 수 있습니다.
먼저 가비지 컬렉터는 약한 참조를 지우므로 참조 대상에 더 이상 액세스할 수 없습니다. 그런 다음 참조를 가져올 수 있는 참조 큐(연관된 항목이 있는 경우)에 배치됩니다.
동시에 이전에 약하게 도달할 수 있었던 개체가 완료됩니다.
2.1. 약한 참조와 부드러운 참조
약한 참조와 소프트 참조의 차이가 명확하지 않은 경우가 있습니다. 소프트 참조는 기본적으로 큰 LRU 캐시입니다. 즉, 참조 대상이 가까운 장래에 재사용될 가능성이 높을 때 소프트 참조를 사용합니다 .
소프트 참조는 캐시 역할을 하므로 참조 대상 자체가 아닌 경우에도 계속해서 도달할 수 있습니다. 실제로 소프트 참조는 다음과 같은 경우에만 수집할 수 있습니다.
- 참조 대상에 강하게 도달할 수 없습니다.
- 소프트 참조가 최근에 액세스되고 있지 않습니다.
따라서 참조 대상에 도달할 수 없게 된 후 몇 분 또는 몇 시간 동안 소프트 참조를 사용할 수 있습니다. 반면에 약한 참조는 참조 대상이 아직 주변에 있는 동안에만 사용할 수 있습니다.
3. 사용 사례
Java 문서에 명시된 바와 같이 약한 참조는 정규화 매핑을 구현하는 데 가장 자주 사용됩니다 . 매핑이 특정 값의 인스턴스를 하나만 보유하는 경우 매핑을 정규화라고 합니다. 새 개체를 생성하는 대신 매핑에서 기존 개체를 찾아 사용합니다.
물론 이러한 참조의 가장 잘 알려진 용도는 WeakHashMap 클래스 입니다. 모든 키가 주어진 키에 대한 약한 참조로 저장되는 맵 인터페이스 의 구현입니다 . 가비지 수집기가 키를 제거하면 이 키와 연결된 엔터티도 삭제됩니다.
자세한 내용 은 WeakHashMap 사용방법(예제)를 확인하세요 .
사용할 수 있는 또 다른 영역은 Lapsed Listener 문제 입니다.
발행자(또는 주제)는 발생한 이벤트에 대해 알리기 위해 모든 구독자(또는 청취자)에 대한 강력한 참조를 보유합니다. 문제는 Listener가 게시자로부터 성공적으로 구독을 취소할 수 없을 때 발생합니다.
따라서 Listener에 대한 강력한 참조를 게시자가 계속 사용할 수 있으므로 Listener를 가비지 수집할 수 없습니다. 결과적으로 메모리 누수가 발생할 수 있습니다.
문제에 대한 해결책은 구독을 취소할 필요 없이 전자가 가비지 수집될 수 있도록 관찰자에 대한 약한 참조를 보유하는 주제일 수 있습니다(이는 완전한 해결책이 아니며, 그렇지 않은 몇 가지 다른 문제를 소개합니다. 여기에서 다룹니다).
4. 약한 참조 작업
약한 참조는 java.lang.ref.WeakReference 클래스로 표시됩니다. 참조 대상을 매개변수로 전달하여 초기화할 수 있습니다. 선택적으로 java.lang.ref.ReferenceQueue 를 제공할 수 있습니다 .
Object referent = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
WeakReference weakReference1 = new WeakReference<>(referent);
WeakReference weakReference2 = new WeakReference<>(referent, referenceQueue);
참조 대상은 get 메소드로 가져올 수 있으며 clear 메소드 를 사용하여 수동으로 제거 할 수 있습니다.
Object referent2 = weakReference1.get();
weakReference1.clear();
이러한 종류의 참조로 안전하게 작업하는 패턴은 소프트 참조 와 동일합니다 .
Object referent3 = weakReference2.get();
if (referent3 != null) {
// GC hasn't removed the instance yet
} else {
// GC has cleared the instance
}
5. 결론
이 빠른 사용방법(예제)에서는 Java의 약한 참조에 대한 하위 수준 개념을 살펴보고 이를 사용하는 가장 일반적인 시나리오에 중점을 두었습니다.