자바 : 강 / 약 / 약 / 팬텀 참조의 차이점


179

주제에 대한 이 기사 를 읽었 지만 실제로 이해하지 못합니다. 개념을 설명 할 때 예제와 함께 조언을 해주십시오.



4
나는 그 문서를 읽었지만 그것이 어떤 차이점을 상상하는 데 도움이되지 않습니다. (그것은 하드 읽기 문서 어쩌면 때문에)

14
그 기사를 읽고도 여전히 이해하지 못한다면, 그에 대한 구체적인 질문이 있습니까? 어떤 부분을 얻지 못했는지에 대한 구체적인 설명 없이는 "Foo를 설명해주세요", "여기서 의미하는 바", "나는 그것을 얻지 못합니다"라고 대답하기가 어렵습니다.
yshavit


@LouisWasserman 상단 링크는 더 이상 유효하지 않습니다.
Mehraj Malik

답변:


142

자바는 서로 다른 두 가지 유형을 제공합니다 /의 클래스 참조 개체 : 강력한약한 . 약한 참조 객체는 소프트팬텀 으로 더 나눌 수 있습니다 .

  • 강한
  • 약한
    • 부드러운
    • 환상

하나씩 살펴 보자.

강력한 참조 객체

StringBuilder builder = new StringBuilder();

다르게 지정되지 않은 경우 이것은 참조 객체의 기본 유형 / 클래스입니다 builder. 강력한 참조 객체입니다. 이러한 종류의 참조는 참조 된 개체가 GC에 적합하지 않게합니다. 즉, 강력한 참조 객체 체인으로 객체를 참조 할 때마다 가비지 수집 할 수 없습니다.

약한 참조 객체

WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);

약한 참조 객체는 참조 객체의 기본 유형 / 클래스가 아니며 사용하려면 위의 예와 같이 명시 적으로 지정해야합니다. 이런 종류의 참조는 참조 객체를 GC에 적합하게 만듭니다. 즉, StringBuilder메모리 에서 객체에 도달 할 수있는 유일한 참조 가 실제로 약한 참조 인 경우 GC는 StringBuilder객체 를 가비지 수집 할 수 있습니다. 메모리에있는 객체에 약한 참조 객체 만 도달 할 수있는 경우 자동으로 GC에 적합합니다.

약점

softphantom 의 두 가지 다른 수준의 약점이 참여할 수 있습니다 .

소프트 목표물 기본적 메모리 A의 남아 이상의 비트 것을 약한 참조 목적 없음 메모리를 사용할 수없고 위험이있을 때까지 통상적으로, 이것은 GC 사이클 내성 OutOfMemoryError(이 경우에는, 제거 할 수)가.

반면, 팬텀 참조 객체는 객체가 메모리에서 효과적으로 제거 된 시점을 정확히 아는 경우에만 유용합니다. 일반적으로 객체는 실제로 객체 자체를 반환하지 않지만 이상한 finalize () 부흥 / 부활 동작 을 수정하는 데 사용됩니다. 메모리 존재를 추적하는 데 도움이 됩니다 .

약한 참조 객체는 캐시 모듈을 구현하는 데 이상적입니다. 실제로, 강력한 참조 체인으로 객체 / 값에 더 이상 도달 할 수 없을 때마다 GC가 메모리 영역을 정리할 수 있도록하여 일종의 자동 제거를 구현할 수 있습니다. 약한 키를 유지 하는 WeakHashMap 이 그 예입니다 .


76

약한 참조 :

간단히 말해서 약한 참조는 객체를 메모리에 유지하기에 충분히 강하지 않은 참조입니다. 약한 참조를 사용하면 가비지 수집기의 접근성을 결정하는 기능을 활용할 수 있으므로 직접 할 필요가 없습니다.

소프트 레퍼런스 :

소프트 참조는 참조하는 개체를 버리려는 열망을 제외하고는 약한 참조와 같습니다. 다음 가비지 수집주기에서 약하게 도달 할 수있는 개체 (가장 약한 참조는 약한 참조)는 삭제되지만 일반적으로 부드럽게 도달 할 수있는 개체는 잠시 동안 고정됩니다.

팬텀 레퍼런스 :

팬텀 참조는 SoftReference 또는 WeakReference와 상당히 다릅니다. 객체의 그립은 너무 작아서 객체를 검색 할 수 없습니다. get () 메서드는 항상 null을 반환합니다. 이러한 참조에 대한 유일한 사용은 참조 된 오브젝트가 죽은 것으로 알고있는 시점에서 ReferenceQueue에 큐에 들어가는 시점을 추적하는 것입니다.

이 텍스트는 https://weblogs.java.net/blog/2006/05/04/understanding-weak-references 에서 추출되었습니다.


1
이 답변의 모든 것이 올바르게 보이지만 연결된 웹 페이지에 오류가있는 것처럼 보입니다. java.lang.ref 패키지 와 PhantomReference 패키지Javadoc 에서는 객체가 더 이상 "팬텀 도달 가능"이 될 때까지 가비지 수집되지 않는다고 제안합니다. 이는 SoftReference와 달리 PhantomReference가 객체가 참조하기 전에 대기열에서 제외되어야 함을 의미합니다. 가비지 수집 ... 및 큐에 대기중인 것은 관련 메모리가 해제되었음을 나타내지 않습니다.
Theodore Murdock 1

2
기록을 위해, 나는 그 블로그 포스트가 정확한 세계에 살고 싶습니다.
시어 도어 머독

1
@TheodoreMurdock javadoc이 정확합니다. 팬텀 참조는 가비지 콜렉션을 전혀 방해하지 않습니다. 객체를 대기열에 넣은 후에는 이미 종료자가 이미 실행되었으므로 종료자가하더라도 저장할 수 없습니다. 죽었지 만 아직 사라지지 않았습니다.
Leliel

@Leliel 사실, 팬텀 참조 실제로 가비지 수집이 대기열에 들어간 후에 실제로 방해합니다 ... 버그가 정리 스레드를 일찍 종료 시키면 최근에 이것을 깨달았습니다. 팬텀 참조의 존재는 모든 팬텀 참조 오브젝트가 힙 덤프에 보유되어 콜렉션에 사용할 수 없도록하는 데 충분 했습니다. 큐를 처리하지 못하거나 큐를 처리 할 때 팬텀 참조가 gc에 적합하지 않은 경우 ( 팬텀 참조를 clear ()하지 않으면 메모리 누수에 팬텀 참조와 참조 된 객체가 모두 포함됩니다.
Theodore Murdock

25

사이의 간단한 차이 SoftReference와는 WeakReference에서 제공하는 안드로이드 개발자 .

a SoftReference와 a 의 차이점 WeakReference은 참조를 지우고 대기열에 넣기로 결정한 시점입니다.

  • SoftReference가급적 늦게 (즉, VM에 메모리가 부족할 위험이있는 경우) A 를 지우고 큐에 넣어야합니다.

  • WeakReference약한 참조로 알려진 즉시 A를 지우고 큐에 넣을 수 있습니다.


16

사용한 세 가지 용어는 주로 가비지 수집 대상의 오브젝트 자격과 관련이 있습니다.

약한 참조 :: 객체가 메모리에 남아있게하기에 충분히 강하지 않은 참조입니다. 그것 가비지 컬렉터의 변덕은 가비지 컬렉션 객체를 수집합니다. GC가이를 수집하지 않도록 강요 할 수는 없습니다 .

Soft Reference :: 약한 참조와 거의 비슷합니다. 그러나 가비지 수집의 약한 참조보다 개체를 조금 더 강력하게 보유한다고 말할 수 있습니다.

가비지 콜렉터가 첫 번째 라이프 사이클 자체에서 약한 참조를 수집하면 다음 가비지 콜렉션주기에서 소프트 참조를 수집합니다.

강력한 참조 :: 위의 두 종류의 참조와 반대입니다. 그들은 쓰레기를 수집하는 것을 좋아하지 않습니다 (대부분 그들은 결코 수집되지 않습니다).

자세한 정보는 다음 링크를 참조하십시오.

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html


3
"가비지 수집가가 첫 번째 수명주기 자체에서 약한 참조를 수집하면 다음 가비지 수집주기에서 소프트 참조를 수집합니다." 반드시 그런 것은 아닙니다. GC가 연속해서 실행될 때 어떻게 확신 할 수 있습니까? GC를 사용하면 2 차 및 3 차에서도 소프트 참조 객체를 살 수 있습니다. 그것에 대한 문서가 없습니다.있는 경우 링크 지정을 언급하십시오.
Saurabh Patil

2
또한 귀하의 답변은 약간 모호합니다.이 문장을보십시오. '약한 참조와 거의 비슷합니다. 그러나 가비지 수집의 약한 참조보다 객체를 조금 더 강력하게 유지한다고 말할 수 있습니다. ' -그는 차이점이 아닌 유사점에 대해 분명히 묻습니다.이 모든 단어는 주제에 대한 명확성보다 혼란을 더합니다.
Saurabh Patil

@SaurabhPatil-당신의 코멘트를 놓쳤다. 여기에 답이 있습니다. 1. "그는 차이점에 대해 명확하게 묻고 유사성이 아니라"-질문에 대한 설명을 참조하십시오 (제목을 "만"은 아님). 2. "하지만 객체를 좀 더 보유하고 있다고 말할 수 있습니다." "SOF는 투표를하고 새로운 답변을 제공 할 수있는 옵션을 제공한다고 생각합니다.
Sabya

14

기사 는 강력하고 부드럽고 약하며 팬텀 참조를 이해하는 데 도움 이 될 수 있습니다.


요약하면

객체에 대한 강력한 참조 가 있으면 GC (Garbage Collector)에서 객체를 수집 / 재생할 수 없습니다.

객체에 대한 약한 참조 만있는 경우 (강한 참조가없는 경우) 다음 GC주기에서 GC가 객체를 회수합니다.

객체에 대한 소프트 참조 만있는 경우 (강한 참조가없는 경우) JVM에 메모리가 부족할 때만 GC가 객체를 회수합니다.

객체가 대기열에 포함되는 시점을 추적하기 위해 객체에 대한 팬텀 참조 를 만듭니다 ReferenceQueue. 세밀한 마무리 작업을 수행 할 수 있음을 알면 (이것은 팬텀 참조가 참조자를 제공하지 않기 때문에 실수로 객체를 부활시키는 것을 방지합니다). 이에 대한 자세한 내용을 보려면 기사를 읽는 것이 좋습니다 .


따라서 강력한 참조는 궁극적 인 힘 을가집니다 (GC에서 수집 할 수 없음).

소프트 참조는 약한 참조보다 강력합니다 (JVM에 메모리가 부족할 때까지 GC주기를 벗어날 수 있음)

약한 참조는 소프트 참조보다 훨씬 강력 하지 않습니다 (GC주기를 벗어날 수 없으며 객체에 다른 강한 참조가없는 경우 회수 됨).


식당 비유

  • 웨이터-GC
  • 당신-힙의 객체
  • 식당 지역 / 공간-힙 공간
  • 신규 고객-식당에서 테이블을 원하는 새로운 객체

이제 당신이 강한 고객 이라면 (강한 참조와 유사하다), 새로운 고객이 식당에 오거나 그와 비슷한 일이 있어도 테이블 (메모리 영역은 힙)을 떠나지 않을 것입니다. 웨이터는 식당을 떠나라고 말할 권리가 없습니다.

당신이 경우 소프트 고객 (소프트 참조 유사)을 새로운 고객이 레스토랑에서 오는 경우 새로운 고객을 수용 왼쪽으로 다른 빈 테이블이없는 경우를 제외하고, 웨이터가 테이블을 떠나하도록 요구하지 않습니다. (즉, 웨이터는 새로운 고객이 들어오고이 새로운 고객을 위해 남은 다른 테이블이없는 경우에만 테이블을 떠나도록 요청합니다)

당신이 약한 고객 (약한 참조와 유사)이라면, 웨이터는 (언제든지) 레스토랑을 떠나라고 요청할 수 있습니다 : P


10

4도 참조- Strong, Weak, Soft, Phantom

강력-일종의 참조이므로 참조 된 개체가 GC에 적합하지 않습니다. 빌더 클래스. 예-StringBuilder

약함-GC에 적합한 참조입니다.

소프트-메모리가 사용 가능할 때까지 오브젝트가 GC에 적합한 일종의 참조입니다. 이미지 캐시에 적합합니다. 메모리를 사용할 수있을 때까지 보관합니다.

팬텀 (Phantom)-객체가 GC에 직접 적합한 레퍼런스의 일종입니다. 객체가 메모리에서 제거 될 때만 알 수 있습니다.

사용합니다 :

  1. 객체가 메모리에서 정확히 제거되는 시점을 식별 할 수 있습니다.

  2. finalize()방법은 오버로드 GC 자격이 두 클래스의 오브젝트를 들어, 다음 GC는 적시에 발생하지 않을 수 있습니다. 따라서 팬텀 참조는 이전에 GC에 적합하게하므로 대부분의 힙이 가비지 인 경우에도 OutOfMemoryErrorsfinalize() 를 얻을 수 있습니다 .

약한 참조는 캐시 모듈을 구현하는 데 이상적입니다.


10

강력한 참조

이들은 우리가 매일 코딩하는 일반적인 객체 참조입니다.

Employee emp = new Employee();

변수 "emp"는 Employee 객체에 대한 강력한 참조를 보유하며 강력한 참조 체인을 통해 도달 할 수있는 객체는 가비지 수집에 적합하지 않습니다. 일반적으로 이것은 원하는 것이지만 항상 그런 것은 아닙니다. 이제 수집 또는 맵의 데이터베이스에서 많은 직원을 가져오고 정기적으로 많은 처리를 수행해야하므로 성능을 유지하려면 캐시에 보관합니다.

이것이 좋지만 지금은 다른 데이터가 필요하며 직원 객체가 필요하지 않으며 캐시 이외의 다른 곳에서는 참조되지 않습니다. 이러한 객체는 사용 중이 아니지만 가비지 수집에 여전히 적합하지 않아 메모리 누수가 발생하는 원인은 무엇입니까? 따라서 여기서는 지루한 전체 캐시를 수동으로 비우거나 약한 참조와 같은 다른 종류의 참조를 사용할 수 있습니다.

약한 참조

약한 참조는 객체를 메모리에 고정하지 않으며 다른 참조에서 참조하지 않으면 다음 GC주기에서 GC됩니다. Java가 제공하는 WeakReference 클래스를 사용하여 위의 종류의 캐시를 만들 수 있습니다.이 캐시는 다른 곳에서 참조되지 않은 객체를 저장하지 않습니다.

WeakReference<Cache> cache = new WeakReference<Cache>(data);

데이터에 액세스하려면 cache.get ()을 호출해야합니다. 약한 참조가 가비지 수집 된 경우이 get 호출은 null을 반환 할 수 있습니다. NPE를 피하려면 반환 된 값을 확인해야합니다. Java는 약한 참조를 사용하는 모음을 제공합니다. 예를 들어 WeakHashMap 클래스는 값이 아닌 키를 약한 참조로 저장합니다. 키가 GC이면지도에서 값이 자동으로 제거됩니다.

약한 참조는 객체이기도하기 때문에이를 정리할 수있는 방법이 필요합니다 (참조하는 객체가 GC 일 때는 더 이상 유용하지 않습니다). 약한 참조를 위해 ReferenceQueue를 생성자에 전달하면 가비지 수집기가 해당 약한 참조를 참조 큐에 추가하거나 최종화하기 전에 참조 큐에 추가합니다. 이 큐를 주기적으로 처리하고 사용 불가능한 참조를 처리 할 수 ​​있습니다.

소프트 레퍼런스

SoftReference는 WeakReference와 유사하지만 가비지 수집 가능성이 적습니다. 메모리 요구에 대한 응답으로 가비지 콜렉터의 재량에 따라 소프트 참조가 지워집니다. 가상 머신은 도달 가능한 오브젝트에 대한 모든 소프트 참조가 OutOfMemoryError를 발생시키기 전에 지워 졌음을 보증합니다.

팬텀 레퍼런스

팬텀 참조는 모든 참조 유형 중에서 가장 약합니다. get on을 호출하면 항상 null이 반환됩니다. 최종화되기 전이나 GC에서 팬텀 참조가 거의 사용되지 않는 약한 참조와 달리 객체는 완료된 후 할당 된 메모리가 회수되기 전에 팬텀으로 참조됩니다.

그래서 그들은 어떻게 유용합니까? 팬텀 참조를 구성 할 때는 항상 ReferenceQueue를 전달해야합니다. 이는 팬텀 참조를 사용하여 객체가 GC 된시기를 볼 수 있음을 나타냅니다.

따라서 최종 참조로 간주되지만 아직 GC가 아닌 약한 참조가 대기열에 포함되면 종료 자 블록에서 객체에 대한 새로운 강력한 참조를 만들고 객체가 GC되지 않도록 할 수 있습니다. 그렇습니다, 그러나 당신은 아마 이것을해서는 안됩니다. 이 경우를 확인하기 위해 팬텀 참조로만 해당 오브젝트에 도달 할 수없는 경우 각 오브젝트에 대해 GC주기가 두 번 발생합니다. 메모리에 많은 가비지가 포함되어 있어도 힙이 부족할 수 있습니다. 팬텀 참조는이를 방지 할 수 있습니다.

내 기사 Java (Strong, Soft, Weak, Phantom)의 참조 유형에 대한 자세한 내용을 읽을 수 있습니다 .


당신은 다른 굴절에서 굴절하지 않으면 다음주기에서 약한 굴절이 GC 될 것이라고 썼다. stron refrence가 어떤 식 으로든 액세스되지 않으면 지워집니다 ... 그렇다면 그렇다면 차이점은 다시 어디에 있습니까? #confused
filemonczyk

1
s1 (strong) 및 s2 (strong)에서 객체를 참조하는 경우 s1과 s2가 모두 역 참조 될 때까지 객체를 가비지 수집 할 수 없지만 s1 (약한) 및 s2 ( strong) 그런 다음 s1은 약한 참조이고 객체에 약한 것을 제외하고 다른 참조가없는 경우 개체는 s2에서만 역 참조 될 때 다음 GC주기에서 가비지 수집에 적합합니다.
Naresh Joshi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.