Jaka jest różnica między SoftReference a WeakReference w Javie?

Jaka jest różnica między java.lang.ref.WeakReference oraz java.lang.ref.SoftReference ?

Author: Sled, 2008-11-18

12 answers

From Understanding Weak References , by Ethan Nicholas:

Słabe referencje

A słabe odniesienie , Mówiąc najprościej, jest odniesienie, które nie jest wystarczająco mocne, aby wymusić, aby obiekt pozostał w pamięci. Słabe referencje pozwalają na wykorzystanie zdolność garbage collector do określ osiągalność dla ciebie, więc ty nie musisz tego robić sam. Ty Utwórz słaby odnośnik w ten sposób:

WeakReference weakWidget = new WeakReference(widget);

I wtedy gdzie indziej w kodzie możesz użyć weakWidget.get() Aby uzyskać rzeczywiste Widget obiekt. Oczywiście słabi Referencja nie jest wystarczająco mocna, aby zapobiegać zbieraniu śmieci, dzięki czemu można znajdź (jeśli nie ma mocnych odniesienia do widgetu), że weakWidget.get() nagle zaczyna Return null.

...

Miękkie referencje

A soft reference jest dokładnie jak słaba Referencja, tyle że mniej chętni do wyrzucenia obiektu do które to dotyczy. Na obiekt, który jest tylko słabo osiągalny (najsilniejszy odniesienia do niego to WeakReferences) zostaną wyrzucone przy następnym śmieciu cyklu zbioru, ale obiekt, który jest miękko osiągalny będzie ogólnie zostań na chwilę.

SoftReferences nie są wymagane aby zachowuj się inaczej niż WeakReferences, ale w praktyce delikatnie osiągalne obiekty są zazwyczaj zachowane tak długo, jak długo pamięć jest w obfity zapas. To czyni je doskonałe podłoże pod pamięć podręczną, takie jako pamięć podręczna obrazu opisana powyżej, ponieważ możesz pozwolić śmieci kolekcjoner martwi się zarówno o to, jak osiągalne są obiekty (silnie osiągalny obiekt nigdy nie zostanie usunięty z cache) i jak bardzo potrzebuje pamięć, którą pochłaniają.

A Peter Kessler dodał komentarz:

Sun JRE traktuje SoftReferences inaczej niż WeakReferences. Staramy się zatrzymać obiekt, do którego odwołuje się SoftReference, jeśli nie ma nacisk na dostępną pamięć. Jeden szczegół: Zasady dla JRE ' ów "-client" I "-server " są różne: JRE-client stara się utrzymać mały ślad poprzez preferowanie wyczyszczenia Softreferencji zamiast rozszerzania sterty, podczas gdy JRE-server stara się utrzymać wysoką wydajność poprzez preferowanie rozszerzenia sterty (jeśli to możliwe) zamiast wyczyszczenia Softreferencji. Jeden rozmiar nie pasuje do wszystkich.

 952
Author: Michael Myers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-31 10:34:31

Słabe odniesienia są zbierane chętnie. Jeśli GC stwierdzi, że obiekt jest słabo osiągalny (osiągalny tylko dzięki słabym referencjom), oczyści słabe odniesienia do tego obiektu natychmiast. Jako takie są dobre dla zachowanie odniesienia do obiektu, dla którego program również przechowuje (silnie odsyłacze)" informacje powiązane " były jakieś, np. buforowane odbicie informacji o klasie, lub wrapperze dla obiektu, itp. Wszystko, co nie ma sensu trzymać po obiekcie, który jest powiązane z is GC-ed. Gdy słaby odnośnik zostanie wyczyszczony, zostanie on Kolejka referencji, że Twój kod gdzieś się wyświetla i odrzuca również obiekty towarzyszące. Oznacza to, że przechowujesz dodatkowe informacje o obiekt, ale informacja ta nie jest potrzebna, gdy obiekt, do którego się odnosi odchodzi. W pewnych sytuacjach można nawet podklasować WeakReference i zachować powiązane dodatkowe informacje o obiekcie w dziedzinie podklasy WeakReference. Kolejny typowy użycie WeakReference jest w połączeniu z mapami do przechowywania kanonicznych instancji.

Softreferencje z drugiej strony są dobre do buforowania zewnętrznych, odtwarzalnych zasobów ponieważ GC zazwyczaj opóźnia ich rozliczenie. Jest jednak gwarantowane, że wszystkie Softreferencje zostaną wyczyszczone przed wyrzuceniem OutOfMemoryError, więc teoretycznie nie może spowodować OOME [*].

Typowym przykładem przypadku użycia jest zachowanie przetworzonej formy treści z plik. Zaimplementowałbyś system, w którym załadowałbyś file, parse it, and keep Softreferencja do głównego obiektu przetworzonej reprezentacji. Następnym razem potrzebujesz pliku, spróbujesz go odzyskać przez SoftReference. Jeśli możesz go odzyskać, oszczędziłeś sobie innego obciążenia/parse, a jeśli GC w międzyczasie wyczyścisz, przeładujesz. W ten sposób korzystasz z darmowych pamięć do optymalizacji wydajności, ale nie ryzykuj wystąpienia.

Teraz na [*]. Utrzymanie SoftReference nie może spowodować OOME sama w sobie. Jeśli z drugiej strony Ty omyłkowo użyj SoftReference dla zadania oznaczonego jako WeakReference do wykorzystania (mianowicie przechowujesz informacje związane z obiektem w jakiś silnie odwołujący się, i odrzuć go, gdy obiekt odniesienia otrzyma cleared), można uruchomić w OOME jako kod, który ankiety Reference i odrzucenia powiązanych obiektów może się zdarzyć, że nie będą działać w odpowiednim czasie Moda.

Więc decyzja zależy od użycia - jeśli buforujesz informacje, które są drogie w budowie, ale niemniej jednak zrekonstruowane z innych danych, użyj miękkich odniesień - jeśli zachowujesz odniesienie do kanonicznej instancji niektórych danych, lub chcesz mieć odniesienie do obiektu bez "posiadania" go (w ten sposób zapobiegając jej GC ' d), użyj słabego odniesienia.

 213
Author: driekken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-18 18:27:02

W Javie ; kolejność od najsilniejszego do najsłabszego występują: Strong, Soft, Weak I Phantom

A Strong reference jest normalnym odniesieniem, które chroni dany obiekt przed zbiorami przez GC. czyli nigdy nie zbieramy śmieci.

A soft reference kwalifikuje się do zbierania przez garbage collector, ale prawdopodobnie nie zostanie pobrany, dopóki jego pamięć nie będzie potrzebna. czyli śmieci zbiera się przed OutOfMemoryError.

A słabe odniesienie jest odniesieniem, które nie chroni obiektu odniesienia przed kolekcją przez GC. czyli śmieci zbiera się, gdy nie ma silnych lub miękkich refów.

A Phantom reference to odniesienie do obiektu, do którego phantomly odwołuje się po jego sfinalizowaniu, ale przed odzyskaniem przydzielonej mu pamięci.

Źródło

Analogia: Załóżmy, że JVM jest królestwem, obiekt jest królem królestwa, a GC jest napastnikiem królestwa, który próbuje zabić król (obiekt).

    Kiedy król jest silny, GC nie może go zabić. Kiedy król jest miękki, GC atakuje go, ale król rządzi królestwem z ochroną, dopóki surowce nie będą dostępne. Kiedy król jest słaby, GC atakuje go, ale włada królestwem bez ochrony. Kiedy king jest Upiorem, GC już go zabiło, ale king jest dostępny za pośrednictwem jego duszy.
 166
Author: Premraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-09 08:50:57

Słabe Odniesienie http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html

Zasada: weak reference jest związany ze śmieciarstwem. Zwykle obiekt posiadający jedną lub więcej reference nie będzie kwalifikował się do usunięcia śmieci.
Powyższa zasada nie ma zastosowania, gdy jest weak reference. Jeśli obiekt ma tylko słabe odniesienie do innych obiektów, to jest gotowy do zbierania śmieci.

Spójrzmy na poniższy przykład: We mieć {[6] } z obiektami, gdzie kluczem jest odniesienie do obiektu.

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());

    }
}

Teraz, podczas wykonywania programu, który stworzyliśmy emp = null. Map trzymanie klucza nie ma tu sensu, ponieważ jest null. W powyższej sytuacji przedmiot nie jest zbierany.

WeakHashMap

WeakHashMap jest taki, w którym wpisy (key-to-value mappings) zostaną usunięte, gdy nie będzie już możliwe ich odzyskanie z Map.

Pozwolę sobie pokazać powyższy przykład tak samo z 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());
    }
}

Wynik: wziął 20 calls to System.gc(), aby uzyskać aMap size z : 0.

WeakHashMap ma tylko słabe odniesienia do kluczy, a nie silne odniesienia, jak inne klasy Map. Są sytuacje, w których musisz się zająć, gdy wartość lub klucz są silnie odwołane, chociaż użyłeś WeakHashMap. Można tego uniknąć, owijając obiekt w 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");
    }
}

Miękkie Referencje.

Soft Reference jest nieco mocniejszy to słabe odniesienie. Soft reference pozwala na zbieranie śmieci, ale prosi garbage collector, aby wyczyścił je tylko wtedy, gdy nie ma innej opcji.

Garbage collector nie zbiera agresywnie miękko osiągalnych obiektów, tak jak to robi z słabo osiągalnymi obiektami - zamiast tego zbiera miękko osiągalne obiekty tylko wtedy, gdy naprawdę "potrzebuje" pamięci. Miękkie odniesienia są sposobem na powiedzenie do śmieciarza: "dopóki pamięć nie jest zbyt ciasna, chciałbym zatrzymać ten obiekt. Ale jeśli pamięć będzie naprawdę napięta, Zbierz ją, a ja się tym zajmę."Garbage collector musi wyczyścić wszystkie miękkie odniesienia, zanim będzie mógł rzucić OutOfMemoryError.

 77
Author: Thalaivar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-21 11:43:18

Jedyna prawdziwa różnica między miękkim odniesieniem a słabym odniesieniem jest taka, że

Garbage collector używa algorytmów, aby zdecydować, czy odzyskać miękko osiągalny obiekt, ale zawsze odzyskuje słaby osiągalny obiekt.

 51
Author: Samir Mangroliya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-31 07:55:17

SoftReference jest przeznaczony do pamięci podręcznej. Gdy okaże się, że WeakReference odwołuje się do nieosiągalnego obiektu, zostanie on natychmiast wyczyszczony. SoftReference może zostać tak jak jest. Zazwyczaj istnieje pewien algorytm odnoszący się do ilości wolnej pamięci i czasu ostatniego użycia, aby określić, czy powinna być wyczyszczona. Aktualnym algorytmem Sun jest wyczyszczenie referencji, jeśli nie została użyta w ciągu tylu sekund, ile megabajtów wolnej pamięci na stercie Java (konfigurowalne, sprawdzanie hotspotu serwera przeciw maksymalnej możliwej stercie określonej przez -Xmx). SoftReference s zostanie wyczyszczone przed wyrzuceniem OutOfMemoryError, chyba że osiągalne jest inaczej.

 25
Author: Tom Hawtin - tackline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-18 18:32:43

Ten artykuł może być bardzo pomocny w zrozumieniu mocnych, miękkich, słabych i fantomowych odniesień.


Aby dać ci podsumowanie,

Jeśli masz tylko słabe odniesienia do obiektu (bez silnych odniesień), to obiekt zostanie odzyskany przez GC w następnym cyklu GC.

Jeśli masz tylko miękkie odniesienia do obiektu (bez silnych odniesień), to obiekt zostanie odzyskany przez GC tylko wtedy, gdy JVM skończy się pamięć.


Więc można powiedzieć, że silne odniesienia mają ostateczną moc (nigdy nie może być pobrany przez GC)

Miękkie odniesienia są potężne niż słabe odniesienia (ponieważ mogą uciec cyklowi GC, dopóki JVM nie skończy się pamięć)

Słabe odniesienia są nawet mniej potężne niż miękkie odniesienia (ponieważ nie mogą pokonać żadnego cyklu GC i zostaną odzyskane, jeśli obiekt nie ma innego silnego odniesienia).


Restauracja Analogia

  • kelner-GC
  • Ty-obiekt w stercie
  • lokal gastronomiczny / lokal użytkowy-lokal użytkowy
  • Nowy Klient-nowy obiekt, który chce stół w restauracji

Teraz, jeśli jesteś silnym klientem (analogicznie do silnego odniesienia), to nawet jeśli nowy klient przychodzi do restauracji lub co tak się dzieje, nigdy nie opuścisz swojego stołu (obszar pamięci na stercie). Kelner nie ma prawa mówić (a nawet prosić) o opuszczenie restauracja.

Jeśli jesteś soft customer (analogicznie do soft reference), wtedy jeśli nowy klient wejdzie do restauracji, kelner nie poprosi Cię o opuszczenie stołu, chyba że nie ma innego pustego stołu, który mógłby pomieścić nowego klienta. (Innymi słowy kelner poprosi Cię o opuszczenie stołu tylko wtedy, gdy wejdzie nowy klient i nie zostanie żaden inny stół dla tego nowego klienta)

Jeśli jesteś słabym klientem (analogicznie do słabego odniesienia), to kelner, do swojej woli, może (w dowolnym momencie) poprosić Cię o opuszczenie restauracji: P

 13
Author: Lavish Kothari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-14 18:28:32

Jedyna Prawdziwa Różnica

Na doc , luźne wątki muszą być oczyszczone przez działającego GC.

Na doc , luźne Softreferencje muszą być wyczyszczone przed wyrzuceniem OOM.

To jedyna prawdziwa różnica. Wszystko inne nie jest częścią umowy. (Zakładam, że najnowsze dokumenty są umowne.)

Softreferencje są przydatne.[[8]} pamięci podręczne wrażliwe na pamięć używają SoftReferences, a nie Słabychreferences.


Na tylko właściwe użycie WeakReference jest do obserwacji przebiegu GC. Robisz to, tworząc nową WeakReference, której obiekt natychmiast wychodzi poza zakres, a następnie spróbuj uzyskać null z weak_ref.get(). / Align = "left" /

Jeśli chodzi o niepoprawne użycie WeakReference, lista jest nieskończona:

  • Kiepski hack do zaimplementowania priorytetu-2 softreference tak, że nie trzeba go pisać, jeszcze nie działa zgodnie z oczekiwaniami ponieważ pamięć podręczna byłaby czyszczona przy każdym uruchomieniu GC, nawet jeśli jest zapasowa pamięć. Zobacz https://stackoverflow.com/a/3243242/632951 dla phails. (Poza tym, co jeśli potrzebujesz więcej niż 2 poziomy priorytetu pamięci podręcznej? I tak potrzebowałbyś do tego prawdziwej biblioteki.)

  • Kiepski hack do kojarzenia danych z obiektem istniejącej klasy, jednak tworzy wyciek pamięci (OutOfMemoryError), gdy twój GC zdecyduje się zrobić przerwę po słabym odczycie. stworzony. Poza tym, to nie jest brzydkie: lepszym podejściem jest użycie krotek.

  • Nędzny hack do powiązania danych z obiektem istniejącej klasy, gdzie klasa ma czelność uczynić się nie-podklasowalną i jest używana w istniejącym kodzie funkcji , który musisz wywołać. W takim przypadku właściwym rozwiązaniem jest albo edycja klasy i uczynienie jej podklasą, albo edycja funkcji i zmuszenie jej do przyjęcia interfejsu zamiast klasy, albo użycie alternatywy funkcja.

 6
Author: Pacerier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 03:27:38

Sześć typów stanów osiągalności obiektów w Javie:

  1. silne ly osiągalne obiekty - GCnie będzie zbierać (odzyskać pamięć zajmowaną przez ) tego rodzaju obiektów. Są to osiągalne przez węzeł główny lub inny silnie osiągalny obiekt (tj. przez zmienne lokalne, zmienne klasowe, zmienne instancji itp.)
  2. Soft ly osiągalne obiekty-GC może próbować zebrać tego rodzaju obiekty w zależności od pamięci spór. Są one dostępne z katalogu głównego przez jeden lub więcej soft reference objects
  3. słabe ly osiągalne obiekty - GCmusi zbierać tego typu obiekty. Te są osiągalne z poziomu głównego przez jeden lub więcej słabych obiektów odniesienia
  4. Resurrect-able objects-GC jest już w trakcie zbierania tych obiektów. Ale [[4]} mogą wrócić do jednego ze Stanów-silnego/miękkiego/słabego przez wykonanie jakiegoś finalizer
  5. Phantom ly osiągalny obiekt - GC jest już w trakcie zbierania tych obiektów i zdecydował, że nie będzie w stanie wskrzesić żadnego finalizera (jeśli sama zadeklaruje metodę finalize (), to jej finalizer zostanie uruchomiony) . Są one osiągalne z poziomu głównego za pomocą jednego lub więcej obiektów odniesienia phantom
  6. Nieosiągalny obiekt-obiekt nie jest ani silnie, ani miękko, ani słabo osiągalny, ani nie jest możliwy do wskrzeszenia. Obiekty te są gotowe do rekultywacji

Więcej Szczegółów: https://www.artima.com/insidejvm/ed2/gc16.html " zwiń

 6
Author: V.Vidyasagar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-17 18:27:23

Należy mieć świadomość, że słabo odwołujący się obiekt zostanie zebrany tylko wtedy, gdy ma tylko słabe odniesienia. Jeśli ma choć jedną mocną referencję, nie zbiera się jej bez względu na to, ile ma słabych referencji.

 1
Author: Fai Lau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-15 04:32:48

Aby dać aspekt wykorzystania pamięci w akcji, zrobiłem eksperyment z silnymi, miękkimi, słabymi i Fantomowymi odniesieniami pod dużym obciążeniem z ciężkimi obiektami, zachowując je do końca programu. Następnie monitorowane użycie sterty i zachowanie GC . Wskaźniki te mogą się różnić w zależności od przypadku, ale z pewnością dają zrozumienie na wysokim poziomie. Poniżej znajdują się wyniki.

Zachowanie sterty i GC pod dużym obciążeniem

  • Strong / Hard Reference {[2] } - ponieważ program kontynuował, JVM nie mógł zebrać zachowany silny obiekt odniesienia. Ostatecznie trafił do "java.lang.OutOfMemoryError: Java heap space "
  • Soft Reference - w miarę jak program kontynuował, użycie heap rosło, ale stare gen GC stało się bliskie max heap. GC zaczęło się nieco później po uruchomieniu programu.
  • słabe odniesienie - w miarę uruchamiania programu obiekty zaczęły finalizować i zbierać się niemal natychmiast. Głównie przedmioty zbierane w śmieciach młodego pokolenia kolekcja.
  • Phantom Reference - podobnie jak weak reference, obiekty odwołujące się do phantom również zaczęły być finalizowane i natychmiast zbierane śmieci. Nie było GC starej generacji i wszystkie przedmioty były zbierane w samym garbage collection młodego pokolenia.

Możesz uzyskać bardziej szczegółowe wykresy, statystyki, obserwacje do tego eksperymentu tutaj .

 1
Author: Ravi K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-24 04:35:13

WeakReference : obiekty, które są tylko słabo odwołane, są zbierane w każdym cyklu GC (minor lub full).

SoftReference : gdy obiekty, które są tylko delikatnie odwołane są zbierane zależy od:

  1. -XX: SoftRefLRUPolicyMSPerMB = N flaga (domyślna wartość to 1000, czyli 1 sekunda)

  2. Ilość wolnej pamięci w stercie.

    przykład:

    • heap ma 10MB wolnego miejsca (po pełnym GC);
    • -XX:SoftRefLRUPolicyMSPerMB=1000

    Wtedy obiekt, do którego odwołuje się tylko SoftReference, zostanie pobrany, jeśli ostatni raz, kiedy był dostępny, jest większy niż 10 sekund.

 0
Author: Artem Petrov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-05 10:12:52