약한 참조의 사용은 구현을 본 적이없는 것이므로 사용 사례가 무엇인지, 구현이 어떻게 작동하는지 파악하려고합니다. 때 당신은을 사용하는 데 필요한 한 WeakHashMap
또는 WeakReference
어떻게 사용 되었는가?
약한 참조의 사용은 구현을 본 적이없는 것이므로 사용 사례가 무엇인지, 구현이 어떻게 작동하는지 파악하려고합니다. 때 당신은을 사용하는 데 필요한 한 WeakHashMap
또는 WeakReference
어떻게 사용 되었는가?
답변:
강력한 참조의 문제점 중 하나는 캐싱, 특히 이미지와 같은 매우 큰 구조에서 발생합니다. 내가 작업하는 웹 사이트 디자인 도구와 같이 사용자 제공 이미지로 작업해야하는 응용 프로그램이 있다고 가정합니다. 디스크에서 이미지를로드하는 것은 매우 비싸기 때문에 한 번에 두 개의 (잠재적으로 거대한) 이미지 사본이 메모리에있을 가능성을 피하고 싶기 때문에 당연히 이러한 이미지를 캐시하려고합니다.
이미지 캐시는 반드시 필요하지 않을 때 이미지를 다시로드하지 못하도록하기 때문에 캐시에 항상 메모리에있는 모든 이미지에 대한 참조가 포함되어 있어야합니다. 그러나 일반적인 강력한 참조를 사용하면 해당 참조 자체로 이미지가 메모리에 남아있게되므로 이미지가 더 이상 메모리에 더 이상 필요하지 않은 시점을 판별하고 캐시에서 이미지를 제거하여 가비지 콜렉션에 적합하게해야합니다. 가비지 수집기의 동작을 복제하고 객체가 메모리에 있어야하는지 여부를 수동으로 결정해야합니다.
약한 참조 이해 , Ethan Nicholas
WeakHashMap
.
WeakReference
대 SoftReference
명확하게 구분할 수있는 한 가지 차이점은 a WeakReference
와 a 의 차이 SoftReference
입니다.
기본적으로 a WeakReference
는 참조 된 객체에 대한 하드 참조 가 없으면 JVM에 의해 간절히 GC-d가 됩니다 . 반면에 d 객체는 실제로 메모리를 회수해야 할 때까지 가비지 수집기에 의해 남겨지는 경향이 있습니다.SoftReference
값 이 WeakReference
s 안에 들어 있는 캐시 는 쓸모가 없습니다 (a WeakHashMap
에서는 약하게 참조되는 키입니다). SoftReferences
사용 가능한 메모리로 증가 및 축소 할 수있는 캐시를 구현할 때 값을 감싸는 데 유용합니다.
WeakReference
s와 WeakHashMap
s 의 일반적인 용도 중 하나 는 객체에 속성을 추가하는 것입니다. 경우에 따라 일부 기능이나 데이터를 객체에 추가하려고하지만 하위 클래스 및 / 또는 컴포지션이 옵션이 아닌 경우 추가하려는 속성으로 확장하려는 객체를 연결하는 해시 맵을 만드는 것이 분명합니다. . 그런 다음 속성이 필요할 때마다지도에서 찾을 수 있습니다. 그러나 속성을 추가하는 객체가 많이 파괴되고 생성되는 경향이있는 경우 맵에서 많은 메모리를 차지하는 오래된 객체가 많이 생길 수 있습니다.
WeakHashMap
대신에 객체 를 사용하는 경우 객체가 더 이상 프로그램의 나머지 부분에서 더 이상 사용되지 않는 즉시 맵을 떠나게되며 이는 바람직한 동작입니다.
나는 몇 가지 데이터를 추가하기 위해이 작업을 수행했다 java.awt.Component
1.4.2과 1.5 사이의 JRE의 변화를 해결하기 위해, 내가 관심 INT (있었다 모든 구성 요소를 서브 클래 싱하여 문제를 해결 한 수 JButton
, JFrame
, JPanel
...) 그러나 이것은 훨씬이었다 훨씬 적은 코드로 쉽게 수행 할 수 있습니다.
또 다른 유용한 경우 WeakHashMap
와 WeakReference
A는 리스너 레지스트리 구현 .
특정 이벤트를 듣고 싶은 것을 만들 때 일반적으로 리스너를 등록합니다.
manager.registerListener(myListenerImpl);
manager
리스너를 리스너에 저장하는 경우 리스너 또는 리스너를 보유한 구성 요소를 사용할 수 없게되면 WeakReference
레지스터 manager.removeListener(myListenerImpl)
가 자동으로 제거되므로 레지스터를 제거 할 필요 가 없습니다.
물론 리스너를 수동으로 제거 할 수는 있지만 잊어 버렸거나 잊어 버린 경우 메모리 누수가 발생하지 않으며 리스너가 가비지 수집되지 않습니다.
WeakHashMap
사진은 어디 에서 나오나요?
등록 된 리스너를 저장하는 리스너 레지스트리 WeakReference
에는 이러한 참조를 저장하기위한 콜렉션이 필요합니다. WeakHashSet
표준 Java 라이브러리 에는 구현 이 없지만 WeakHashMap
후자를 쉽게 사용하여 첫 번째 기능을 "구현"할 수 있습니다.
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
이를 통해 listenerSet
새 리스너를 등록하기 만하면 리스너를 세트에 추가하기 만하면됩니다. 명시 적으로 제거되지 않더라도 리스너가 더 이상 참조되지 않으면 JVM에 의해 자동으로 제거됩니다.
WeakHashMap
가 필요할 때마다 있습니다 HashMap
. 그래서 와우 수동으로 할 필요가 없습니다 hashmap.remove을 이제까지 하여 obj가 범위 밖으로되면 항목이 자동적으로 제거되기 때문에! 말 그대로 마술! 그런 추악한 마술 해킹은 완전한 페이스 팜 입니다.
WeakReference
코드 기반 을 크게 단순화하고 구독 취소 실패와 관련된 불필요한 버그를 피합니다. 어떤 단점이 있습니까?
이 블로그 게시물은 Java : ID에서 동기화 두 클래스의 사용법을 보여줍니다 . 사용법은 다음과 같습니다.
private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();
public void performTask(String resourceId) {
IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
synchronized (mutext) {
// look up the resource and do something with it
}
}
IdMutextProvider는 동기화 할 id 기반 객체를 제공합니다. 요구 사항은 다음과 같습니다.
이는 다음 유형의 내부 스토리지 맵을 사용하여 수행됩니다.
WeakHashMap<Mutex, WeakReference<Mutex>>
객체는 키와 가치입니다. 맵 외부에 객체에 대한 하드 참조가없는 경우 가비지 수집 될 수 있습니다. 맵의 값은 하드 참조와 함께 저장되므로 메모리 누수를 방지하기 위해 값을 WeakReference 에 래핑해야합니다 . 이 마지막 요점은 javadoc 에서 다룹니다 .
예를 들어 특정 클래스로 작성된 모든 객체를 추적하려는 경우. 이러한 객체가 가비지 수집되도록하려면 객체 자체 대신 객체에 대한 약한 참조 목록 / 맵을 유지하십시오.
이제 누군가 팬텀 참조를 설명 할 수 있다면 기쁠 것입니다 ...
전술 한 바와 같이, 강한 참조가 존재하는 한 약한 참조가 유지된다.
예를 들어 리스너 내부에서 WeakReference를 사용하면 대상 객체에 대한 기본 참조가 없어지면 리스너가 더 이상 활성화되지 않습니다. 이는 WeakReference가 리스너 목록에서 제거됨을 의미하지는 않으며 정리가 여전히 필요하지만 예를 들어 스케줄 된 시간에 수행 될 수 있습니다. 이것은 또한 수신 된 객체가 강력한 참조를 보유하지 못하게하고 결국 메모리 팽창의 원인이되는 것을 방지하는 효과가 있습니다. 예 : 창보다 수명이 더 긴 모델을 참조하는 스윙 GUI 구성 요소.
위에서 설명한 것처럼 청취자를 가지고 놀면서 우리는 객체가 사용자의 관점에서 "즉시"수집된다는 것을 빠르게 깨달았습니다.
내가 약한 참조에 실제로 사용했던 한 가지 사례는 거의 사용되지 않는 하나의 매우 큰 객체를 사용하는 것입니다. 필요하지 않을 때 메모리에 보관하고 싶지 않습니다. 그러나 다른 스레드에 동일한 객체가 필요한 경우 두 개의 메모리 중 하나를 원하지 않습니다. 어딘가에 객체에 대한 약한 참조를 유지하고 그것을 사용하는 방법에 대한 하드 참조를 유지할 수 있습니다. 메소드가 모두 완료되면 오브젝트가 수집됩니다.
"new WeakHashMap ()"에 대한 Google 코드 검색을 수행했습니다.
나는 GNU classpath 프로젝트에서 많은 일치를 얻었고