IT이야기

Java에서 SoftReference와 WeakReference의 차이점은 무엇입니까?

cyworld 2022. 6. 7. 21:33
반응형

Java에서 SoftReference와 WeakReference의 차이점은 무엇입니까?

와의 차이는 무엇입니까?

Weak References에서 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의 정책은 다릅니다.클라이언트 JRE는 히프를 확장하는 것보다 SoftReferences를 클리어하는 것을 선호하며, 반면 -server JRE는 SoftReferences를 클리어하는 것보다 히프를 확장함으로써 높은 성능을 유지하려고 합니다.한 가지 사이즈로 모든 것을 맞출 수는 없다.

약한 참고 문헌은 열심히 수집된다.GC는 오브젝트가 약하게 도달할 수 없다고 판단한 경우(약한 참조를 통해서만 도달할 수 있음), 그 오브젝트에 대한 약한 참조를 즉시 클리어합니다.따라서 클래스에 대한 캐시된 리플렉션 정보나 객체에 대한 래퍼 등과 같이 프로그램이 "관련 정보"를 보관(강력하게 참조)하는 객체에 대한 참조를 유지하는 데 유용합니다.연관된 오브젝트 뒤에 유지하는 것이 의미가 없는 것은 모두 GC-ed입니다.취약한 참조가 클리어되면 코드가 폴링하는 참조 큐에 큐잉되어 관련 오브젝트도 폐기됩니다.즉, 객체에 대한 추가 정보는 유지되지만 해당 객체가 참조하는 객체가 사라지면 해당 정보는 필요하지 않습니다.실제로 상황에 따라서는 WeakReference 서브클래스를 분류하여 개체에 대한 추가 정보를 WeakReference 서브클래스의 필드에 유지할 수도 있습니다.WeakReference의 또 다른 일반적인 용도는 Maps와 함께 표준 인스턴스를 유지하는 것입니다.

한편 SoftReferences는 GC에 의해 일반적으로 삭제가 지연되기 때문에 외부 재생 가능한 리소스를 캐싱하는 데 유용합니다.단, Out Of Memory Error가 발생하기 전에 모든 Soft References가 클리어되므로 이론적으로는 OOE[*]를 발생시킬 수 없습니다.

일반적인 사용 예로는 파일에서 컨텐츠의 구문 분석 형식을 유지하는 것이 있습니다.파일을 로드하여 해석하고 해석된 표현의 루트 객체에 대한 SoftReference를 유지하는 시스템을 구현합니다.다음 번에 파일이 필요할 때 SoftReference를 통해 파일을 가져옵니다.취득할 수 있는 경우는, 다른 부하/파스를 회피하고, 그 사이에 GC가 클리어 했을 경우는, 새로고침합니다.이렇게 하면 성능 최적화를 위해 여유 메모리를 활용할 수 있지만 OOE의 위험을 감수할 필요는 없습니다.

[*]에 대해서SoftReference를 유지하는 것 자체가 OOE를 발생시킬 수는 없습니다.한편 태스크에 대해 SoftReference를 잘못 사용한 경우(즉, WeakReference는 어떤 형태로든 강하게 참조된 개체와 관련된 정보를 유지하고 참조 개체가 클리어되면 이를 폐기함), ReferenceQueue를 폴링하여 관련 개체를 폐기하는 코드로서 OOE에 접속할 수 있습니다.때아닌가 보다

따라서, 그 결정은 사용법에 따라 달라집니다.구축 비용이 많이 드는 정보를 캐싱하는 경우에도 다른 데이터로부터 재구성할 수 있는 경우에는 소프트 레퍼런스를 사용합니다.일부 데이터의 표준 인스턴스에 대한 참조를 유지하고 있거나 오브젝트를 "소유"하지 않고 오브젝트에 대한 참조를 원하는 경우(따라서 GC가 되지 않도록 합니다).언급.

Java에서는 가장 강한 것부터 가장 약한 것까지 순서에는 Strong, Soft, Weak, Phantom이 있습니다.

Strong 참조는 참조된 객체를 GC에 의한 수집으로부터 보호하는 일반 참조입니다.쓰레기는 절대 모으지 않는다.

소프트 참조는 가비지 컬렉터로 수집할 수 있지만 메모리가 필요할 때까지 수집되지 않을 수 있습니다(예: 가비지 수집 이전).OutOfMemoryError.

Weak 참조는 참조된 개체를 GC에 의한 수집으로부터 보호하지 않는 참조입니다. 즉, Strong 또는 Soft 참조가 없을 때 가비지가 수집됩니다.

팬텀 참조는 오브젝트가 완료된 후 할당된 메모리가 회수되기 전에 팬텀 참조되는 오브젝트에 대한 참조입니다.

원천

유추:JVM이 킹덤, 오브젝트가 킹덤, GC가 킹덤의 공격자이며 킹덤(오브젝트)을 죽이려 한다고 가정합니다.

  • 킹이 강할 때 GC는 그를 죽일 수 없다.
  • 킹이 소프트일 경우 GC는 킹을 공격하지만 킹은 자원을 이용할 수 있을 때까지 왕국을 보호하며 지배합니다.
  • 킹이 약할 때 GC는 그를 공격하지만 왕국을 보호 없이 지배한다.
  • 왕이 팬텀일 때, GC는 이미 그를 죽였지만, 왕은 그의 영혼을 통해 이용할 수 있다.

취약한 참조 http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html

원칙: weak reference가비지 수집과 관련되어 있습니다.일반적으로 개체는 하나 또는 여러 개를 가지고 있습니다.reference가비지 수집 대상이 되지 않습니다.
위의 원칙은 다음과 같은 경우에는 적용되지 않습니다.weak reference. 객체가 다른 객체에 대한 참조가 약한 경우 가비지 수집 준비가 됩니다.

다음 예를 보겠습니다.저희 회사에는Map개체(Key는 개체 참조)를 사용합니다.

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위의 경우 오브젝트는 가비지가 수집되지 않습니다.

Weak Hash Map

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.

소프트 레퍼런스(soft reference)와 약한 레퍼런스(weak reference)의 유일한 실질적인 차이점은

가비지 컬렉터는 알고리즘을 사용하여 소프트 도달 가능한 개체를 회수할지 여부를 결정하지만 항상 약하게 도달 가능한 개체를 회수합니다.

SoftReference는 캐시용으로 설계되어 있습니다.가 판명되었을 때WeakReference그렇지 않으면 도달할 수 없는 오브젝트를 참조하면 오브젝트는 즉시 클리어 됩니다. SoftReference그대로 둘 수 있습니다.통상, 빈 메모리의 양과 소거할지를 결정하기 위해서 마지막으로 사용한 시간에 관한 알고리즘이 있습니다.현재의 Sun 알고리즘은 Java 힙에 사용 가능한 메모리(MB)가 있는 만큼 몇 초 동안 사용되지 않은 경우 참조를 지우는 것입니다(설정 가능한 서버 HotSpot은 다음에서 설정한 최대 가능한 힙에 대해 검사합니다).-Xmx).SoftReference이 클리어되기 전에OutOfMemoryError특별히 도달하지 않는 한, 이 느려집니다.

문서는 강하고, 부드럽고, 약하고, 팬텀적인 참조를 이해하는 데 매우 도움이 될 수 있습니다.


요약하자면

오브젝트에 대한 참조가 약한 경우(강력한 참조가 없는 경우), 오브젝트는 다음 GC 사이클에서 GC에 의해 회수됩니다.

개체에 대한 소프트 참조만 있는 경우(강력한 참조는 없음), JVM의 메모리가 부족할 때만 GC에 의해 개체가 회수됩니다.


따라서 강력한 레퍼런스는 궁극의 파워를 가지고 있다고 할 수 있습니다(GC에서는 절대 수집할 수 없습니다).

소프트 레퍼런스는 약한 레퍼런스보다 강력합니다(JVM의 메모리가 부족해질 때까지 GC 사이클을 회피할 수 있습니다).

약한 참조는 소프트 참조보다 더 강력하지 않습니다(GC 사이클을 이스케이프할 수 없으며 객체에 다른 강력한 참조가 없는 경우 재사용됩니다).


레스토랑의 비유

  • 웨이터 - GC
  • 사용자 - 힙 내의 개체
  • 레스토랑 영역/공간 - 힙 공간
  • 새 고객 - 레스토랑에 테이블을 원하는 새 개체

만약 당신이 강한 고객이라면(강력한 참고문헌과 유사), 레스토랑에 새로운 손님이 와도 테이블(메모리 영역 더미)을 떠나지 않습니다.웨이터는 당신에게 레스토랑에서 나가라고 말할 권리가 없습니다.

당신이 부드러운 손님이라면(부드러운 참조와 유사), 새로운 손님이 레스토랑에 들어왔을 때 웨이터는 새로운 손님을 수용할 빈 테이블이 남아 있지 않으면 자리를 비우라고 하지 않습니다.(즉, 웨이터는 새로운 고객이 들어와 이 새로운 고객을 위한 다른 테이블이 없는 경우에만 테이블에서 나가라고 요구합니다.)

만약 당신이 약한 고객(유사하고 약한 참조)이라면, 웨이터는 그의 뜻에 따라 언제든지 당신에게 레스토랑을 떠나라고 요청할 수 있습니다.p

Java에서는 다음 6가지 유형의 객체 도달 가능성 상태가 있습니다.

  1. 강하게 도달할 수 있는 오브젝트 - GC는 이러한 오브젝트를 수집(사용한 메모리를 재청구)하지 않습니다.루트 노드 또는 다른 강력한 도달 가능 개체(로컬 변수, 클래스 변수, 인스턴스 변수 등)를 통해 도달할 수 있습니다.
  2. Soft reachable objects - GC는 메모리 경합에 따라 이러한 종류의 오브젝트를 수집하려고 할 수 있습니다.1개 이상의 소프트 참조 개체를 통해 루트에서 도달할 수 있습니다.
  3. 약하게 도달할 수 있는 개체 - GC는 이러한 종류의 개체를 수집해야 합니다.하나 이상의 취약한 참조 개체를 통해 루트에서 연결할 수 있습니다.
  4. 부활 가능한 개체 - GC가 이미 이러한 개체를 수집하는 중입니다.그러나 일부 피니셔 실행으로 인해 Strong/Soft/Weak 상태 중 하나로 돌아갈있습니다.
  5. Phantomally reachable object - GC는 이미 이러한 오브젝트를 수집하고 있으며 어떤 파이널라이저에서도 부활할 수 없다고 판단되었습니다(finalize() 메서드 자체를 선언하면 파이널라이저는 이미 실행되고 있습니다).하나 이상의 팬텀 참조 개체를 통해 루트에서 연결할 수 있습니다.
  6. 도달할 수 없는 개체 - 개체는 강하고, 부드럽게, 약하게 또는 팬텀에 도달할 수 없으며 부활할 수 없습니다.이러한 개체는 회수할 수 있습니다.

상세한 것에 대하여는, https://www.artima.com/insidejvm/ed2/gc16.html 를 참조해 주세요.

유일한 진정한 차이점

문서에 따르면 Loose WeakReferences는 실행 중인 GC에서 클리어해야 합니다.

문서에 따르면 OOM을 던지기 전에 느슨한 SoftReferences를 클리어해야 합니다.

그게 유일한 진짜 차이점이야.그 외는 모두 계약서가 아닙니다.(최신 문서는 계약서라고 가정합니다.)

SoftReferences는 편리합니다.메모리에 민감한 캐시는 WeakReferences가 아닌 SoftReferences를 사용합니다.


The only 적절한 use of WeakReference is to observe the GC run. You do this by creating a new WeakReference whose object immediately goes out of scope, then try to get null out of weak_ref.get(). When it's null, you learn that between this duration, the GC ran.

WeakReference의 잘못된 사용에 대해서는 목록이 끝없이 표시됩니다.

  • priority-2 소프트 레퍼런스를 실장하기 위한 불량한 해킹이 있기 때문에 쓸 필요가 없습니다만, GC를 실행할 마다 캐시가 클리어 되기 때문에, 스페어 메모리가 있는 경우에서도, 예상대로 동작하지 않습니다.https://stackoverflow.com/a/3243242/632951 를 참조해 주세요.(게다가 캐시 priority가 2개 이상 필요한 경우는 어떻게 해야 합니까?그러기 위해서는 아직 진짜 라이브러리가 필요합니다.)

  • 데이터를 기존 클래스의 객체에 관련짓는 형편없는 해킹이지만 약한 참조가 생성된 후 GC가 휴식을 취하기로 결정하면 메모리 누전(Out Of Memory Error)이 발생합니다.게다가 못생긴 것 이상입니다. 더 좋은 방법은 튜플을 사용하는 것입니다.

  • 데이터를 기존 클래스의 객체와 연관짓는 형편없는 해킹. 클래스는 자신을 서브클래스로 만들 용기가 있으며 호출해야 하는 기존 함수 코드에 사용됩니다.이 경우 적절한 해결책은 클래스를 편집하여 하위 분류 가능 상태로 만들거나 함수를 편집하여 클래스가 아닌 인터페이스를 취하도록 하거나 대체 함수를 사용하는 것입니다.

동작중의 메모리 사용의 측면을 나타내기 위해서, 프로그램 종료까지, 무거운 물체와 함께 무거운 부하가 걸린 상태에서의 Strong, Soft, Weak, Phantom의 레퍼런스를 실험했습니다.다음으로 히프 사용량 및 GC 동작을 모니터링합니다.이러한 지표는 상황에 따라 다를 수 있지만 높은 수준의 이해를 제공합니다.다음은 조사 결과입니다.

고부하 시 힙 및 GC 동작

  • Strong/Hard Reference - 프로그램이 계속 진행됨에 따라 JVM에서 유지된 Strong Reference 개체를 수집할 수 없습니다.결국 "java.lang"이 되었다.Out Of Memory Error: Java 힙 공간"
  • Soft Reference - 프로그램이 계속 진행됨에 따라 힙 사용량이 증가했지만 OLD gen GC는 최대 힙에 가까워지고 있었습니다.프로그램을 시작한 후 GC가 비트를 늦게 시작했습니다.
  • 취약한 참조 - 프로그램이 시작되자마자 오브젝트가 완성되어 수집되기 시작했습니다.대부분 젊은 세대의 가비지 컬렉션에 수집되었습니다.
  • 팬텀 레퍼런스 - 약한 레퍼런스와 마찬가지로 팬텀 레퍼런스 오브젝트도 즉시 완성되어 가비지가 수집됩니다.구세대 GC는 없었고 모든 오브젝트가 젊은 세대의 가비지 컬렉션 자체에 수집되고 있었습니다.

실험에 대한 자세한 그래프, 통계량, 관측치는 여기에서 확인할 수 있습니다.

약하게 참조되는 개체는 약하게 참조되는 개체만 있는 경우에만 수집된다는 점에 유의해야 합니다.만약 그것이 하나의 강한 참조를 가지고 있다면, 그것은 아무리 약한 참조를 가지고 있어도 수집되지 않는다.

WeakReference: 약하게만 참조되는 개체는 모든 GC 사이클(소수 또는 전체)에서 수집됩니다.

SoftReference: 부드럽게만 참조되는 객체가 수집되는 경우 다음 항목에 따라 달라집니다.

  1. -XX: SoftRefLRUPoolyMSPerMB=N 플래그(기본값은 1000, 1초)

  2. 힙 내의 사용 가능한 메모리 양입니다.

    예:

    • 힙에 10MB의 여유 공간이 있습니다(풀 GC 후).
    • -XX: SoftRefLRUPolicyMSPerMB=1000

    마지막으로 접근한 시간이 10초를 넘으면 SoftReference에서만 참조되는 개체가 수집됩니다.

언급URL : https://stackoverflow.com/questions/299659/whats-the-difference-between-softreference-and-weakreference-in-java

반응형