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


810

9
SoftReferences są rodzajem (nie do końca, ale ze względu na dyskusję) WeakReferences, które są zwykle gromadzone, gdy JVM uważa, że ​​brakuje pamięci.
Ajeet Ganga,

5
@AjeetGanga, Luźne słabe referencje są zawsze gromadzone za każdym razem, gdy działa GC. Patrz stackoverflow.com/a/46291143/632951
Pacerier

Odpowiedzi:


926

Ze zrozumienia słabych referencji Ethana Nicholasa:

Słabe referencje

Słaby odniesienia , po prostu, jest odniesienie że nie jest wystarczająco silny, aby zmusić obiekt pozostanie w pamięci. Słabe referencje pozwalają ci wykorzystać zdolność śmieciarza do określenia twojej osiągalności, więc nie musisz tego robić sam. Tworzysz słabe odniesienie, takie jak to:

WeakReference weakWidget = new WeakReference(widget);

a następnie w innym miejscu w kodzie można użyć weakWidget.get()do uzyskania rzeczywistego Widgetobiektu. Oczywiście słabe odwołanie nie jest wystarczająco silne, aby zapobiec wyrzucaniu elementów bezużytecznych, więc możesz znaleźć (jeśli nie ma silnych odniesień do widżetu), który weakWidget.get()nagle zaczyna wracać null.

...

Miękkie odniesienia

Miękkie odniesienia jest dokładnie jak słaby odniesienia, z tym że jest to mniej chętnie wyrzucić obiekt, do którego się odnosi. Obiekt, który jest tylko słabo osiągalny (najsilniejsze odniesienia do niego WeakReferences), zostanie odrzucony w następnym cyklu wyrzucania elementów bezużytecznych, ale obiekt, do którego można łatwo dotrzeć, na ogół pozostanie na chwilę.

SoftReferencesnie muszą zachowywać się inaczej niż WeakReferences, ale w praktyce obiekty łatwo osiągalne są na ogół zatrzymywane, dopóki pamięć jest bogata. To sprawia, że ​​są doskonałym fundamentem pamięci podręcznej, takiej jak pamięć podręczna obrazów opisana powyżej, ponieważ możesz pozwolić śmieciarzowi martwić się zarówno o to, jak osiągalne są obiekty (silnie osiągalny obiekt nigdy nie zostanie usunięty z pamięci podręcznej), a także jak źle potrzebuje pamięci, którą zużywają.

I Peter Kessler dodał w komentarzu:

Środowisko JRE firmy Sun traktuje SoftReferences inaczej niż WeakReferences. Próbujemy trzymać się obiektu, do którego odwołuje się SoftReference, jeśli nie ma presji na dostępną pamięć. Jeden szczegół: zasady dla środowiska JRE „-client” i „-server” są różne: środowisko JRE -client próbuje utrzymać mały ślad, woląc wyczyścić SoftRefereferencje niż rozwinąć stertę, podczas gdy środowisko JRE -server próbuje zachować wysoka wydajność, woląc rozwinąć stertę (jeśli to możliwe) niż wyczyścić SoftReferences. Jeden rozmiar nie pasuje do wszystkich.


7
Post już nie jest dostępny, można go znaleźć na maszynie powrotnej
riccardo.tasso

tym razem archiwum nie jest już dostępne
użytkownik1506104

209

Słabe referencje są gromadzone chętnie. Jeśli GC stwierdzi, że obiekt jest słabo osiągalny (osiągalny tylko przez słabe odniesienia), natychmiast usunie słabe odniesienia do tego obiektu. Jako takie, są dobre do przechowywania odniesienia do obiektu, dla którego twój program również przechowuje (silnie odwoływane) „powiązane informacje” gdzieś, takie jak buforowane informacje o odbiciu dotyczące klasy lub opakowanie obiektu itp. Wszystko, co tworzy nie ma sensu zachowywać się po obiekcie, z którym jest skojarzony, jest GC-ed. Kiedy słabe odniesienie zostanie usunięte, zostanie umieszczone w kolejce w kolejce referencyjnej, w której twój kod odpytuje gdzieś, i odrzuca również powiązane obiekty. Oznacza to, że przechowujesz dodatkowe informacje o obiekcie, ale informacje te nie są potrzebne, gdy obiekt, do którego się odnosi, zniknie. Tak właściwie, w niektórych sytuacjach można nawet podklasować WeakReference i zachować powiązane dodatkowe informacje o obiekcie w polach podklasy WeakReference. Innym typowym zastosowaniem WeakReference jest połączenie z Mapami do przechowywania instancji kanonicznych.

Z drugiej strony SoftReferences są dobre do buforowania zewnętrznych zasobów, które można odzyskać, ponieważ GC zwykle opóźnia ich usunięcie. Jest jednak pewne, że wszystkie SoftRefereferencje zostaną usunięte przed zgłoszeniem OutOfMemoryError, więc teoretycznie nie mogą spowodować OOME [*].

Typowym przykładem użycia jest przechowywanie przeanalizowanej formy zawartości z pliku. Wdrożysz system, w którym ładujesz plik, parsujesz go i przechowujesz SoftReference do obiektu głównego analizowanej reprezentacji. Następnym razem, gdy będziesz potrzebować pliku, spróbujesz go odzyskać poprzez SoftReference. Jeśli możesz go odzyskać, oszczędziłeś sobie kolejnego ładowania / analizy, a jeśli GC wyczyściło go w międzyczasie, przeładujesz go. W ten sposób wykorzystujesz wolną pamięć do optymalizacji wydajności, ale nie ryzykujesz OOME.

Teraz dla [*]. Utrzymywanie SoftReference nie może samo w sobie powodować OOME. Jeśli z drugiej strony omyłkowo użyjesz SoftReference do zadania, do którego należy użyć WeakReference (tzn. Zachowasz informacje powiązane z obiektem w jakiś sposób silnie przywołane i odrzucisz je, gdy obiekt odniesienia zostanie wyczyszczony), możesz uruchomić OOME jako Twój kod, który odpytuje ReferenceQueue i odrzuci powiązane obiekty, może nie działać w odpowiednim czasie.

Tak więc decyzja zależy od użycia - jeśli buforujesz informacje, które są drogie w budowie, ale mimo to można je odtworzyć z innych danych, użyj miękkich odniesień - jeśli trzymasz odniesienie do kanonicznej instancji niektórych danych lub chcesz mieć odniesienie do obiektu bez „posiadania go” (tym samym uniemożliwiając GC'd), użyj słabego odniesienia.


14
Szczególnie przydatny do wyjaśnienia, kiedy zostaną użyte słabe obiekty.
Jack BeNimble

Kluczową kwestią dotyczącą właściwego użycia a WeakReferencejest to, że w miejscach, w których należy go używać, fakt, że można zachować ważność przez chwilę po tym, jak odniesienie wykracza poza zakres, może być dopuszczalny, ale nie jest pożądany.
supercat

Próbuję zrozumieć, do czego służy WeakHashMap, jeśli zawsze produkuje słabe odniesienie do obiektu kluczowej wartości?

@ supercat, Jest tylko jedno właściwe zastosowanie, WeakReferenceaby obserwować działania GC. Patrz opracowanie: stackoverflow.com/a/46291143/632951
Pacerier

1
@Pacerier: Autor tego postu po prostu się myli. Pomija niektóre inne scenariusze użycia, takie jak subskrypcja zdarzeń, jego drugi punkt jest nonsensowny, a trzeci punkt zakłada, że ​​programista może robić rzeczy, które mogą być niemożliwe. Jego pierwsza uwaga jest rozsądna, ale wiąże się bezpośrednio z tym, co powiedziałem. Jeśli kod często będzie musiał budować i porównywać duże niezmienne obiekty, na przykład część budowlana będzie często tańsza, jeśli kod utworzy nowe obiekty bez względu na to, czy już istnieją, ale porównanie między obiektem a nim samym (identyczne odwołania) będzie ...
supercat,

155

W Javie ; porządek od najsilniejszego do najsłabszego, są to: Strong, Soft, Weak i Phantom

Wyraźne odniesienie jest normalną odniesienia, który chroni określonego obiektu ze zbioru za pomocą GC. tj. Nigdy nie zbiera śmieci.

Odniesienia Miękkie jest uprawniony do odbioru przez śmieciarza, lecz prawdopodobnie nie zostaną zebrane, aż potrzebna jest jego pamięć. tj. śmieci są zbierane wcześniej OutOfMemoryError.

Słaby odniesienia jest punktem odniesienia, który nie odwołuje się do ochrony obiektu ze zbioru za pomocą chromatografii gazowej. tzn. śmieci są zbierane, gdy nie ma silnych lub miękkich ref.

Odniesienia Phantom jest odniesienie do obiektu jest określany po phantomly została sfinalizowana, ale przed jej przydzielona pamięć została odzyskana.

Źródło

Analogia: Załóżmy, że JVM to królestwo, Object to król królestwa, a GC to atakujący królestwo, który próbuje zabić króla (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 ochroną, dopóki zasoby nie będą dostępne.
  • Kiedy Król jest Słaby , GC atakuje go, ale rządzi królestwem bez ochrony.
  • Kiedy królem jest Upiór , GC już go zabił, ale król jest dostępny przez jego duszę.

7
Miękkie odniesienie ... until memory is availablenie ma sensu. Czy masz na myśli is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use?
ToolmakerSteve,

1
tak, śmieciarz nie zbierze referencji, dopóki pamięć nie będzie dostępna.
Premraj

2
Lubię proste wyjaśnione rzeczy, bez zbyt dużej ilości bla bla bla +1 ode mnie!
Adelin,

3
Doskonałe podsumowanie z innowacyjnym przykładem
Ravindra babu


77

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

Zasada: weak reference jest związana z odśmiecaniem. Zwykle obiekt posiadający jeden lub więcej referencenie będzie kwalifikował się do odśmiecania.
Powyższa zasada nie ma zastosowania, gdy jest weak reference. Jeśli obiekt ma tylko słabe odniesienie do innych obiektów, jest gotowy do odśmiecania.

Spójrzmy na poniższy przykład: Mamy Mapz Obiektami, w których Klucz odnosi się 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 wykonaliśmy emp = null. MapPrzytrzymanie klawisza nie ma sensu tutaj, jak to jest null. W powyższej sytuacji obiekt nie jest odśmiecany.

WeakHashMap

WeakHashMapto taki, w którym wpisy ( key-to-value mappings) zostaną usunięte, gdy nie będzie już można ich odzyskać z Map.

Pokażę 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());
    }
}

Wyjście: zajęło 20 calls to System.gc()wynik aMap size: 0.

WeakHashMapma tylko słabe odniesienia do kluczy, a nie silne odniesienia jak inne Mapklasy. Są sytuacje, na które musisz uważać, gdy wartość lub klucz jest silnie przywołany, mimo że użyłeś WeakHashMap. Można tego uniknąć, zawijają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 Referencejest nieco silniejszy od tego słabego odniesienia. Miękkie odniesienie pozwala na wyrzucanie elementów bezużytecznych, ale prosi moduł czyszczący o jego usunięcie tylko wtedy, gdy nie ma innej opcji.

Śmieciarka nie zbiera agresywnie obiektów miękko osiągalnych, tak jak ma to miejsce w przypadku słabo osiągalnych - zamiast tego zbiera przedmioty miękko osiągalne tylko wtedy, gdy naprawdę „potrzebuje” pamięci. Miękkie odniesienia to sposób na powiedzenie śmieciarzowi: „Dopóki pamięć nie jest zbyt ciasna, chciałbym utrzymać ten obiekt w pobliżu. Ale jeśli pamięć staje się naprawdę ciasna, idź i zbierz ją, a ja zajmę się z tym." Śmieciarka musi wyczyścić wszystkie miękkie odniesienia, zanim będzie mogła je wyrzucić OutOfMemoryError.


5
Można uzyskać NullPointerExceptionin aMap.get().put(...).
xehpuk

Twój pierwszy przykład HashMap wygląda źle. Kiedy robisz „aMap.put (emp, val);” zarówno „emp”, jak i „val” są mocnymi odniesieniami. Wewnętrznie tworzona jest nowa zmienna, która przechowuje „emp” i „val”, więc po wykonaniu „emp = null;” po prostu niwelujesz zmienną „emp”, ale nie zmienną wewnętrznie do mapy skrótu (która nadal zawiera oryginalny obiekt Employee). Dlatego mapa haszowa nadal będzie zawierać silne odniesienie do „emp” niezależnie od tego, co zrobisz ze zmienną „emp” na zewnątrz.
Tiago,

@Tiago. Nie. Prawdopodobnie przez „pierwszy przykład” masz na myśli ten WeakHashMapprzykład (ponieważ jest to pierwszy, który wykazuje Słabe zachowanie). Spójrz na dokument „WeakHashMap”: "An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. " Cały sens używania WeakHashMap polega na tym , że nie musisz deklarować / przekazywać WeakReference; WeakHashMap robi to za Ciebie wewnętrznie. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
ToolmakerSteve

Wziął 0 wywołań do System.gc (), aby uzyskać rozmiar słabyHashMap: 0 jest wyjściem drugiego programu?
Adelin

1
Inny przykład WeakHashMapdziałania z przykładową aplikacją pokazującą, w jaki sposób wpisy są usuwane dopiero po wykonaniu odśmiecania, zobacz moją odpowiedź na pytanie, czy WeakHashMap ciągle rośnie, czy też usuwa klucze od śmieci? .
Basil Bourque

50

Jedyną prawdziwą różnicą między miękkim odniesieniem a słabym odniesieniem jest to

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


@ATorras, Samir. Rozwinąłem tę odpowiedź tutaj: stackoverflow.com/a/46291143/632951
Pacerier

25

SoftReferencejest przeznaczony do pamięci podręcznych. Kiedy okaże się, że WeakReferenceodwołuje się do obiektu nieosiągalnego w inny sposób, zostanie natychmiast wyczyszczony. SoftReferencemoże pozostać tak jak jest. Zazwyczaj istnieje pewien algorytm związany z ilością wolnej pamięci i czasem ostatnio używanym do ustalenia, czy należy ją wyczyścić. Obecny algorytm firmy Sun polega na usunięciu odwołania, jeśli nie zostało użyte przez tyle sekund, ile w sterty Java jest wolnych megabajtów (konfigurowalne, HotSpot serwera sprawdza maksymalną możliwą stertę ustawioną przez -Xmx). SoftReferences zostanie wyczyszczony przed OutOfMemoryErrorrzuceniem, chyba że jest osiągalny inaczej.


9
Ale w Androidzie nie zaleca się
używania

4
@DoctororDrive tbf pytanie dotyczyło java, a nie dalviku! :-P
fabspro

2
@YaroslavMytkalyk, Szczerze mówiąc, jeśli Android chce przepisać zachowanie klasy, powinien używać własnej przestrzeni nazw, a nie java.lang. Takie nadużycie synonimów nie przynosi pożytku.
Pacerier

9

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


Aby dać ci streszczenie,

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

Jeśli masz tylko miękkie odniesienia do obiektu (bez silnych odniesień), obiekt zostanie odzyskany przez GC tylko wtedy, gdy w JVM zabraknie pamięci.


Możesz więc powiedzieć, że silne referencje mają najwyższą moc (nigdy nie mogą być zebrane przez GC)

Miękkie odniesienia są potężniejsze niż słabe odniesienia (ponieważ mogą uciec cyklowi GC, dopóki w maszynie JVM zabraknie pamięci)

Słabe referencje są nawet mniej skuteczne niż miękkie (ponieważ nie mogą wykasować żadnego cyklu GC i zostaną odzyskane, jeśli obiekt nie ma innych silnych referencji).


Restauracja Analogia

  • Kelner - GC
  • Ty - Obiekt w kupie
  • Obszar / przestrzeń restauracji - przestrzeń sterty
  • Nowy klient - nowy obiekt, który chce stołu w restauracji

Teraz, jeśli jesteś silnym klientem (analogicznie do mocnego odniesienia), to nawet jeśli nowy klient przyjdzie do restauracji lub coś takiego się wydarzy, nigdy nie opuścisz stołu (obszar pamięci na stosie). Kelner nie ma prawa powiedzieć ci (ani nawet poprosić) o opuszczenie restauracji.

Jeśli jesteś miękkim klientem (analogicznie do miękkiego odniesienia), to jeśli nowy klient przyjdzie do restauracji, kelner nie poprosi cię o opuszczenie stolika, chyba że nie pozostanie już inny pusty stolik, aby pomieścić nowego klienta. (Innymi słowy, kelner poprosi cię o opuszczenie stołu tylko wtedy, gdy wejdzie nowy klient i nie będzie już innego stołu dla tego nowego klienta)

Jeśli jesteś słabym klientem (analogicznie do słabej referencji), to kelner, z własnej woli, może (w dowolnym momencie) poprosić cię o opuszczenie restauracji: P


7

Jedyna prawdziwa różnica

Zgodnie z dokumentem luźne WeakReferences muszą zostać usunięte przez działający GC.

Zgodnie z dokumentem luźne SoftRefereferencje muszą zostać wyczyszczone przed wyrzuceniem OOM.

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

Przydatne są SoftReferences. Pamięci wrażliwe na pamięć używają SoftReferences, a nie WeakReferences.


Jedynym właściwym zastosowaniem WeakReference jest obserwacja przebiegu GC. Robisz to poprzez utworzenie nowego WeakReference, którego obiekt natychmiast wychodzi poza zakres, a następnie próbujesz uzyskać wartość null weak_ref.get(). Kiedy się nulldowiesz, dowiesz się, że między tym czasem trwała GC.

Jeśli chodzi o nieprawidłowe użycie WeakReference, lista jest nieograniczona:

  • kiepski włamanie do implementacji miękkiego odwołania o priorytecie 2, tak że nie musisz go pisać, ale to nie działa zgodnie z oczekiwaniami, ponieważ pamięć podręczna byłaby czyszczona przy każdym uruchomieniu GC, nawet gdy jest wolna pamięć. Zobacz https://stackoverflow.com/a/3243242/632951, aby zapoznać się ze szczegółami. (Poza tym, co jeśli potrzebujesz więcej niż 2 poziomów priorytetu pamięci podręcznej? Wciąż potrzebujesz do tego prawdziwej biblioteki).

  • kiepski włamanie do powiązania danych z obiektem istniejącej klasy, ale powoduje przeciek pamięci (OutOfMemoryError), gdy twoja GC postanawia zrobić sobie przerwę po utworzeniu twoich słabych preferencji. Poza tym jest to brzydkie: lepszym rozwiązaniem jest użycie krotek.

  • kiepski hack do kojarzenia danych z obiektem istniejącej klasy, gdzie klasa ma odwagę, by stać się nieklasowalnym, 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 sprawienie, by przyjmowała interfejs zamiast klasy, lub skorzystała z funkcji alternatywnej.


Co z pamięcią podręczną, w której typem klucza equals()jest po prostu tożsamość obiektu? Miękkie odniesienia wydają się marnotrawstwem, ponieważ gdy kluczowy obiekt nie będzie już osiągalny, nikt już nie będzie przeglądał tego mapowania.
HighCommander4,

Nie zgadzam się. Użyj WeakReference, jeśli i tak nie chcesz wpływać na GC (możesz zapisać odwołanie do obiektu, a następnie sprawdzić, czy nadal istnieje, bez żadnych preferencji). Użyj SoftReference, jeśli chcesz wpłynąć na GC, aby spróbować zatrzymać obiekt (tj. Kiedy wolisz, aby GC go zatrzymał).
David Refaeli

Dobrym przykładem zastosowania WeakReference jest AsyncTask Androida - aby zachować instancję kontekstu. W ten sposób, jeśli kontekst umrze (jeśli aktywność - obrót ekranu itp.), AsyncTask nie będzie miał do niego żadnych silnych odniesień, a więc może być wyrzucany. Sprawdź youtu.be/…
David Refaeli

3

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

  1. Silnie osiągalne obiekty - GC nie będzie zbierać ( odzyskiwać pamięci zajmowanej przez ) tego rodzaju obiekty. Można je osiągnąć za pośrednictwem węzła głównego lub innego łatwo osiągalnego obiektu (tj. Za pomocą zmiennych lokalnych, zmiennych klas, zmiennych instancji itp.)
  2. Miękko osiągalne obiekty - GC może próbować zbierać tego rodzaju obiekty w zależności od rywalizacji o pamięć. Można do nich dotrzeć z korzenia za pomocą jednego lub więcej miękkich obiektów odniesienia
  3. Słabo osiągalne obiekty - GC musi zbierać tego rodzaju obiekty. Można do nich dotrzeć z korzenia za pomocą jednego lub więcej słabych obiektów odniesienia
  4. Obiekty wskrzeszające - GC już zbiera te obiekty. Ale mogą wrócić do jednego ze stanów - Strong / Soft / Weak po wykonaniu jakiegoś finalizatora
  5. Obiekt osiągalny fantomowo - GC jest już w trakcie zbierania tych obiektów i zdecydował, że nie będzie wskrzeszony przez żaden finalizator (jeśli sam zadeklaruje metodę finalizującą (), to jego finalizator zostanie uruchomiony) . Można je osiągnąć od zera za pomocą jednego lub więcej fantomowych obiektów odniesienia
  6. Nieosiągalny obiekt - Obiekt nie jest ani silnie, miękko, słabo ani fantomowo osiągalny i nie można go wskrzesić. Te obiekty są gotowe do regeneracji

Aby uzyskać więcej informacji: https://www.artima.com/insidejvm/ed2/gc16.html «zwiń


4
Nie jest to dobry opis odniesień fantomowych. Wymieniłeś 4 typy w osobnej kolejności. „fantom” jest najsłabszym typem, a nie najsilniejszym. Tradycyjna kolejność ich wymieniania to „silny, miękki, słaby, fantom”. I nie mam pojęcia, skąd masz pojęcie, że obiekty fantomowe są używane do mechanizmów buforowania. AFAIK, są to stan tymczasowy widziany tylko przez GC, a nie coś, z czym mógłby pracować zwykły programista.
ToolmakerSteve,

@ToolmakerSteve i wszyscy - przepraszam za kilka rzeczy 1. złe wyjaśnienie odwołań Phantom w poprzedniej wersji mojej odpowiedzi oraz 2. Opóźnienie w poprawianiu błędów. Teraz poprawiono odpowiedź, poprawiając błędy
V.Vidyasagar,

1

Należy zdawać sobie sprawę z tego, że słabo referencyjny obiekt zostanie zebrany tylko wtedy, gdy będzie miał TYLKO słabe referencje. Jeśli ma tyle silnych odniesień, nie zostanie zebrane bez względu na liczbę słabych odniesień.


To zdrowy rozsądek ... to samo dotyczy softref i phantomref.
Pacerier

1

Aby nadać aspektowi użycia pamięci w działaniu, przeprowadziłem eksperyment z odniesieniami Strong, Soft, Weak & Phantom pod dużym obciążeniem ciężkimi przedmiotami, zachowując je do końca programu. Następnie monitorowano użycie sterty i zachowanie GC . Dane te mogą się różnić w zależności od przypadku, ale z pewnością zapewniają wysoki poziom zrozumienia. Poniżej znajdują się ustalenia.

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

  • Silne / twarde odniesienie - w miarę kontynuowania programu JVM nie mógł zebrać zachowanego silnego obiektu odniesienia. W końcu trafił do „java.lang.OutOfMemoryError: Java heap space”
  • Miękkie odniesienie - w miarę kontynuowania programu, zużycie sterty wciąż rosło, ale stało się GC OLD gen, gdy zbliżało się maksimum sterty. GC rozpoczęło się nieco później po uruchomieniu programu.
  • Słabe referencje - W momencie uruchomienia programu obiekty zaczęły się finalizować i zbierać niemal natychmiast. Przeważnie przedmioty zostały zebrane podczas wywozu śmieci młodego pokolenia.
  • Phantom Reference - Podobnie jak w przypadku słabych odniesień, obiekty odniesienia fantomowe również zaczęły być finalizowane, a śmieci są natychmiast zbierane. Nie było GC starej generacji i wszystkie obiekty były gromadzone w samym śmiecie dla młodego pokolenia.

Możesz uzyskać więcej szczegółowych wykresów, statystyk, obserwacji dla tego eksperymentu tutaj .


0

WeakReference : obiekty, do których odniesienia są słabo przywoływane, są gromadzone w każdym cyklu GC (mniejszym lub pełnym).

SoftReference : kiedy gromadzone są obiekty, do których odwołuje się tylko miękkie odniesienie, zależy od:

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

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

    Przykład:

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

    Następnie obiekt, do którego odwołuje się tylko SoftReference, zostanie zebrany, jeśli ostatni raz, gdy był dostępny, jest dłuższy niż 10 sekund.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.