답변:
Ethan Nicholas의 약한 참조 이해 에서 :
약한 참조
약한 참조 , 간단히 넣어, 메모리에 남아있는 개체를 강제로 강한 것만으로는 충분하지 않습니다 참조입니다. 약한 참조를 사용하면 가비지 수집기의 접근성을 결정하는 기능을 활용할 수 있으므로 직접 할 필요가 없습니다. 다음과 같이 약한 참조를 만듭니다.
WeakReference weakWidget = new WeakReference(widget);
그런 다음 코드의 다른 곳에서
weakWidget.get()
실제Widget
객체 를 얻는 데 사용할 수 있습니다 . 물론 약한 참조는 가비지 수집을 방지하기에 충분히 강력하지 않으므로weakWidget.get()
갑자기 위젯을 참조하지 않는 경우 ( 갑자기 위젯에 대한 참조가없는 경우) 가 반환되기 시작할 수null
있습니다....
소프트 레퍼런스
소프트 참조는 참조하는 객체를 버릴 이하 열망하는 것을 제외하고, 정확히 약한 참조 같다.
WeakReferences
다음 가비지 수집주기에서 약하게 도달 할 수있는 개체 (가장 강한 참조 )는 삭제되지만 일반적으로 부드럽게 도달 할 수있는 개체는 잠시 동안 고정됩니다.
SoftReferences
와 다르게 동작 할 필요 는WeakReferences
없지만, 실제로 메모리에 충분한 공급이있는 한 소프트 도달 가능한 객체는 일반적으로 유지됩니다. 가비지 수집기가 개체에 접근 가능한 방법 (강력한 개체는 캐시에서 절대 제거 되지 않음 )과 얼마나 나쁜지에 대해 가비지 수집기에 대해 염려 할 수 있기 때문에 이는 위에서 설명한 이미지 캐시와 같은 캐시의 훌륭한 기반 이됩니다. 그들이 소비하는 메모리가 필요합니다.
그리고 Peter Kessler는 다음과 같이 논평했습니다 :
Sun JRE는 SoftReferences를 WeakReferences와 다르게 처리합니다. 사용 가능한 메모리에 압력이 없으면 SoftReference가 참조하는 객체를 유지하려고 시도합니다. "-client"및 "-server"JRE에 대한 정책이 다릅니다. -client JRE는 힙을 확장하지 않고 SoftReference를 지우는 것을 선호하여 풋 프린트를 작게 유지하려고하지만, -server JRE는 명확한 SoftReference 대신 힙을 확장하는 것을 선호하여 성능을 향상시킵니다. 하나의 크기가 모든 것에 맞지는 않습니다.
약한 참조는 열심히 수집됩니다. GC가 객체에 약한 도달 가능 (약한 참조를 통해서만 도달 할 수 있음)이 발견되면 해당 객체에 대한 약한 참조가 즉시 지워집니다. 따라서, 클래스에 대한 캐시 된 리플렉션 정보 또는 객체의 래퍼 등과 같이 프로그램이 "강하게 참조 된" "관련 정보"를 유지하는 객체에 대한 참조를 유지하는 데 좋습니다. 연결된 개체가 GC 버전 이후에 유지되는 것은 의미가 없습니다. 약한 참조가 지워지면 코드가 어딘가에서 폴링하는 참조 큐에 대기하고 관련 개체도 삭제됩니다. 즉, 개체에 대한 추가 정보를 유지하지만 해당 개체가 사라지면 해당 정보가 필요하지 않습니다. 사실은, 특정 상황에서는 WeakReference를 서브 클래 싱하고 WeakReference 서브 클래스의 필드에 객체에 대한 관련 추가 정보를 유지할 수도 있습니다. WeakReference의 또 다른 일반적인 사용은 표준 인스턴스를 유지하기 위해 맵과 함께 사용하는 것입니다.
반면에 SoftReferences는 GC가 일반적으로 삭제를 지연시키기 때문에 재생 가능한 외부 리소스를 캐싱하는 데 좋습니다. OutOfMemoryError가 발생하기 전에 모든 SoftReference가 지워지도록 보장되므로 이론적으로 OOME [*]을 유발할 수 없습니다.
일반적인 사용 사례는 파싱 된 형식의 내용을 파일에서 유지하는 것입니다. 파일을로드하고 파싱 한 다음 구문 분석 된 표현의 루트 객체에 대한 SoftReference를 유지하는 시스템을 구현해야합니다. 다음에 파일이 필요할 때 SoftReference를 통해 파일을 검색하려고합니다. 검색 할 수 있으면 다른로드 / 파싱을 아끼지 않았으며 GC에서로드를 지우면 다시로드합니다. 이렇게하면 성능 최적화를 위해 사용 가능한 메모리를 사용하지만 OOME의 위험은 없습니다.
이제 [*]입니다. SoftReference를 유지한다고해서 OOME 자체가 발생하지는 않습니다. 반면에 실수로 약한 참조를 사용하여 작업에 약한 참조를 사용하는 경우 (즉, 개체와 관련된 정보를 어떻게 든 강력하게 참조하고 참조 개체가 지워지면 버리는 경우) OOME을 실행할 수 있습니다. ReferenceQueue를 폴링하고 관련 개체를 삭제하는 코드는 적시에 실행되지 않을 수 있습니다.
따라서 결정은 사용량에 따라 결정됩니다. 구성하는 데 비용이 많이 들지만 다른 데이터에서 재구성 할 수있는 정보를 캐싱하는 경우 소프트 참조를 사용하십시오. 일부 데이터의 정식 인스턴스에 대한 참조를 유지하거나 원하는 경우 "소유"하지 않은 객체에 대한 참조가 있으므로 (GC되지 않도록) 약한 참조를 사용하십시오.
WeakReference
그것을 사용해야하는 곳에서 참조가 범위를 벗어난 후에도 잠시 동안 유효하게 유지 될 수 있다는 사실은 견딜 수 있지만 바람직하지는 않다는 것입니다.
WeakReference
. 정교함 참조 : stackoverflow.com/a/46291143/632951
자바에서 ; 가장 강한 것부터 가장 약한 것까지 순서가 있습니다 : 강함, 약함, 약함 및 팬텀
강한 참조는 GC에 의해 수집에서 언급 된 목적을 보호하는 정상 기준이다. 즉 가비지 수집을하지 마십시오.
소프트 참조는 가비지 컬렉터에 의해 수집 대상이지만, 아마도 메모리가 필요할 때까지 수집되지 않습니다. 즉 가비지 수집 전에 OutOfMemoryError
.
약한 참조는 GC에 의해 수집에서 참조 된 개체를 보호하지 않는 기준이다. 즉 가비지 수집은 Strong 또는 Soft 참조가 없을 때 수집됩니다.
팬텀 참조는 객체에 대한 참조 phantomly가 확정 된 후에 언급하지만, 그 할당 된 메모리는 회수되기 이전이다.
유추 : JVM이 왕국이고, Object가 왕국의 왕이고, GC는 왕 (객체)을 죽이려는 왕국의 공격 자라고 가정합니다.
until memory is available
의미가 없습니다. 당신은 의미 is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
합니까?
약한 참조 http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
원리 : weak reference
가비지 수집과 관련이 있습니다. 일반적으로 하나 이상의 객체 reference
는 가비지 수집에 적합하지 않습니다.
위의 원칙은 적용되지 않습니다 weak reference
. 객체가 다른 객체와 참조가 약한 경우 가비지 수집 준비가 완료됩니다.
아래 예제를 보자 Map
. Key가 객체를 참조 하는 with 객체가 있습니다.
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> aMap = new
HashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
System.out.println("Size of Map" + aMap.size());
}
}
이제 프로그램을 실행하는 동안 우리는 만들었습니다 emp = null
. Map
그대로 유지 키 여기에 이해되지 않는다 null
. 위의 상황에서 개체는 가비지 수집되지 않습니다.
약한 해시지도
WeakHashMap
key-to-value mappings
더 이상 에서 항목 을 검색 할 수 없을 때 항목 ( )이 제거 되는 항목 Map
입니다.
위의 예제를 WeakHashMap 과 동일하게 보여 드리겠습니다.
import java.util.WeakHashMap;
public class Test {
public static void main(String args[]) {
WeakHashMap<Employee, EmployeeVal> aMap =
new WeakHashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
int count = 0;
while (0 != aMap.size()) {
++count;
System.gc();
}
System.out.println("Took " + count
+ " calls to System.gc() to result in weakHashMap size of : "
+ aMap.size());
}
}
출력 : 툭 20 calls to System.gc()
에서 결과 aMap size
의 : 0.
WeakHashMap
키에 대한 약한 참조 만 있고 다른 Map
클래스 와 같은 강한 참조는 없습니다 . 값이나 키를 사용했지만 강력하게 참조 할 때주의해야 할 상황이 있습니다 WeakHashMap
. 이것은 WeakReference에 객체를 랩핑함으로써 피할 수 있습니다 .
import java.lang.ref.WeakReference;
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> map =
new HashMap<Employee, EmployeeVal>();
WeakReference<HashMap<Employee, EmployeeVal>> aMap =
new WeakReference<HashMap<Employee, EmployeeVal>>(
map);
map = null;
while (null != aMap.get()) {
aMap.get().put(new Employee("Vinoth"),
new EmployeeVal("Programmer"));
System.out.println("Size of aMap " + aMap.get().size());
System.gc();
}
System.out.println("Its garbage collected");
}
}
소프트 레퍼런스.
Soft Reference
약한 참조보다 약간 강합니다. 소프트 참조는 가비지 콜렉션을 허용하지만 다른 옵션이없는 경우에만 가비지 콜렉터에서이를 지우도록 요청합니다.
가비지 수집기는 약한 도달 가능한 객체와는 달리 부드럽게 도달 가능한 객체를 적극적으로 수집하지 않고 실제로 메모리에 "필요한"경우에만 도달 가능한 부드러운 객체를 수집합니다. 소프트 참조는 가비지 콜렉터에게 말하는 방법입니다. "메모리가 너무 빡빡하지 않으면이 오브젝트를 유지하고 싶습니다. 그러나 메모리가 정말 빡빡하면 계속해서 수집하여 처리하겠습니다. 그것으로." 가비지 수집기는 모든 소프트 참조를 삭제해야 던져 질 수 있습니다 OutOfMemoryError
.
NullPointerException
있는을 aMap.get().put(...)
.
WeakHashMap
예를 나타냅니다 (약한 동작을 보여주는 첫 번째 예이므로). "의 WeakHashMap"에 대한 문서에서 봐 : "An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. "
의 WeakHashMap를 사용하는 전체 포인트는 것입니다 당신이 패스에 WeakReference를 / 선언 할 필요는 없습니다; WeakHashMap은 내부적으로이를 수행합니다. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
WeakHashMap
항목 만 제거하는 방법을 예제 응용 프로그램을 보여주는 행동에, 후 가비지 콜렉션이 실행 참조 내 대답 질문에이 IS의 WeakHashMap은 계속 성장하거나 쓰레기 키를 삭제합니까? .
소프트 레퍼런스와 약한 레퍼런스의 유일한 차이점은
가비지 콜렉터는 알고리즘을 사용하여 부드럽게 도달 가능한 오브젝트를 회수할지 여부를 결정하지만 항상 약한 도달 가능한 오브젝트를 회수합니다.
SoftReference
캐시 용으로 설계되었습니다. WeakReference
도달 할 수없는 객체를 참조하는 것이 발견 되면 즉시 지워집니다. SoftReference
그대로 남아있을 수 있습니다. 일반적으로 사용 가능한 메모리 양과 메모리를 지 울지 여부를 결정하는 데 사용 된 시간과 관련된 일부 알고리즘이 있습니다. 현재 Sun 알고리즘은 Java 힙에 사용 가능한 메가 바이트의 메모리가있는 시간 (초)에 사용되지 않은 경우 참조를 지우는 것 -Xmx
입니다. SoftReference
s OutOfMemoryError
도달 할 수없는 한 s가 처리되기 전에 지워집니다 .
java.lang
. 이러한 동의어의 남용은 아무 소용이 없습니다.
이 기사 는 강력하고 부드럽고 약하며 팬텀 참조를 이해하는 데 도움 이 될 수 있습니다.
요약하면
개체에 대한 참조 가 약한 경우 (강한 참조가없는 경우) 다음 GC주기에서 GC가 개체를 회수합니다.
객체에 대한 소프트 참조 만있는 경우 (강한 참조가없는 경우) JVM에 메모리가 부족할 때만 GC가 객체를 회수합니다.
따라서 강력한 참조는 궁극적 인 힘 을가집니다 (GC에서 수집 할 수 없음).
소프트 참조는 약한 참조보다 강력합니다 (JVM에 메모리가 부족할 때까지 GC주기를 벗어날 수 있음)
약한 참조는 소프트 참조보다 훨씬 강력 하지 않습니다 (GC주기를 초과 할 수 없으며 객체에 다른 강한 참조가없는 경우 회수 됨).
식당 비유
이제 당신이 강한 고객 이라면 (강한 참조와 유사하다), 새로운 고객이 식당에 오거나 그와 비슷한 일이 있어도 테이블 (메모리 영역은 힙)을 떠나지 않을 것입니다. 웨이터는 식당을 떠나라고 말할 권리가 없습니다.
당신이 경우 소프트 고객 (소프트 참조 유사)을 새로운 고객이 레스토랑에서 오는 경우 새로운 고객을 수용 왼쪽으로 다른 빈 테이블이없는 경우를 제외하고, 웨이터가 테이블을 떠나하도록 요구하지 않습니다. (즉, 웨이터는 새로운 고객이 들어오고이 새로운 고객을 위해 다른 테이블이 남아 있지 않은 경우에만 테이블을 떠나도록 요청합니다)
당신이 약한 고객 (약한 참조와 유사)이라면, 웨이터는 (언제든지) 레스토랑을 떠나라고 요청할 수 있습니다 : P
당 다큐먼트 , 느슨한있는 WeakReferences이 있어야 실행중인 GC에 의해 삭제 될 수있다.
doc 당 , 느슨한 SoftReferences 는 OOM이 발생하기 전에 지워 져야합니다 .
이것이 유일한 차이점입니다. 그 밖의 모든 것은 계약의 일부가 아닙니다. (최신 문서는 계약이라고 가정합니다.)
SoftReferences가 유용합니다. 메모리에 민감한 캐시는 약한 참조가 아닌 SoftReference를 사용합니다.
weak_ref.get()
. 이 때 null
, 당신은이 기간, GC가 실행 된 사이에 그 내용.
WeakReference 를 잘못 사용하면 목록은 끝이 없습니다.
형편 해킹 당신이 하나를 작성하지 않아도되도록 우선 순위 2하는 SoftReference를 구현하는, 그러나 그것은 캐시에서 삭제 될 수 있기 때문에 예상대로 작동하지 않습니다 모든 여분의 메모리가있는 경우에도, GC 실행. phails에 대해서는 https://stackoverflow.com/a/3243242/632951 을 참조 하십시오 . (또한, 2 단계 이상의 캐시 우선 순위가 필요한 경우 어떻게해야합니까? 여전히 실제 라이브러리가 필요합니다.)
데이터를 기존 클래스의 객체와 연결하기위한 거친 해킹 이지만 GC가 약한 참조가 생성 된 후 휴식을 취하기로 결정할 때 메모리 누수 (OutOfMemoryError)를 생성합니다. 게다가, 그것은 추악한 것 이상입니다 : 더 나은 접근법은 튜플을 사용하는 것입니다.
데이터를 기존 클래스의 객체와 연결하기위한 거친 해킹. 클래스는 서브 클래스화할 수없는 신경을 가지고 있으며 호출해야하는 기존 함수 코드 에서 사용됩니다 . 이러한 경우 적절한 해결책은 클래스를 편집하여 서브 클래스 가능하게 만들거나, 함수를 편집하여 클래스 대신 인터페이스를 사용하거나 대체 함수를 사용하는 것입니다.
equals()
이 단지 객체 아이덴티티 인 캐시 는 어떻습니까? 핵심 객체에 더 이상 접근 할 수 없으면 소프트 매핑은 낭비되는 것처럼 보입니다.
Java에서 6 가지 유형의 객체 도달 가능성 상태 :
자세한 내용은 https://www.artima.com/insidejvm/ed2/gc16.html «축소
작동중인 메모리 사용 측면을 제공하기 위해 프로그램이 끝날 때까지 무거운 객체를 사용하여 무거운 물건으로 무거운 하중을받는 Strong, Soft, Weak & Phantom 참조를 실험했습니다. 그런 다음 힙 사용 및 GC 동작을 모니터링했습니다 . 이러한 측정 항목은 사례마다 다를 수 있지만 확실히 높은 수준의 이해를 제공합니다. 결과는 다음과 같습니다.
고하 중에서 힙 및 GC 동작
이 실험에 대한 깊이 그래프, 통계, 관측치에 대한 자세한 내용은 여기를 참조하십시오 .
WeakReference를 : 약하게 참조하는 객체가 모든 GC주기에 수집 (미성년자 또는 전체).
SoftReference : 부드럽게 참조되는 오브젝트가 수집되는시기는 다음에 따라 다릅니다.
-XX : SoftRefLRUPolicyMSPerMB = N 플래그 (기본값은 1000, 일명 1 초)
힙에서 사용 가능한 메모리의 양입니다.
예:
SoftReference가 참조한 오브젝트는 마지막으로 액세스 한 시간이 10 초보다 크면 수집됩니다.