Jaka jest różnica między java.lang.ref.WeakReference
i java.lang.ref.SoftReference
?
java
reference
weak-references
soft-references
driekken
źródło
źródło
Odpowiedzi:
Ze zrozumienia słabych referencji Ethana Nicholasa:
I Peter Kessler dodał w komentarzu:
źródło
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.
źródło
WeakReference
jest 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.WeakReference
aby obserwować działania GC. Patrz opracowanie: stackoverflow.com/a/46291143/632951W 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).
źródło
until memory is available
nie ma sensu. Czy masz na myśliis eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
?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ęcejreference
nie 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
Map
z Obiektami, w których Klucz odnosi się do obiektu.Teraz podczas wykonywania programu, który wykonaliśmy
emp = null
.Map
Przytrzymanie klawisza nie ma sensu tutaj, jak to jestnull
. W powyższej sytuacji obiekt nie jest odśmiecany.WeakHashMap
WeakHashMap
to taki, w którym wpisy (key-to-value mappings
) zostaną usunięte, gdy nie będzie już można ich odzyskać zMap
.Pokażę powyższy przykład tak samo z WeakHashMap
Wyjście: zajęło
20 calls to System.gc()
wynikaMap size
: 0.WeakHashMap
ma tylko słabe odniesienia do kluczy, a nie silne odniesienia jak inneMap
klasy. 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 .Miękkie referencje.
Soft Reference
jest 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
.źródło
NullPointerException
inaMap.get().put(...)
.WeakHashMap
przykł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.htmlWeakHashMap
dział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? .Jedyną prawdziwą różnicą między miękkim odniesieniem a słabym odniesieniem jest to
źródło
SoftReference
jest przeznaczony do pamięci podręcznych. Kiedy okaże się, żeWeakReference
odwołuje się do obiektu nieosiągalnego w inny sposób, zostanie natychmiast wyczyszczony.SoftReference
moż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
).SoftReference
s zostanie wyczyszczony przedOutOfMemoryError
rzuceniem, chyba że jest osiągalny inaczej.źródło
java.lang
. Takie nadużycie synonimów nie przynosi pożytku.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
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
źródło
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ęnull
dowiesz, 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.
źródło
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.Sześć typów stanów osiągalności obiektów w Javie:
Aby uzyskać więcej informacji: https://www.artima.com/insidejvm/ed2/gc16.html «zwiń
źródło
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ń.
źródło
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
Możesz uzyskać więcej szczegółowych wykresów, statystyk, obserwacji dla tego eksperymentu tutaj .
źródło
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:
-XX: SoftRefLRUPolicyMSPerMB = Flaga N (wartość domyślna to 1000, czyli 1 sekunda)
Ilość wolnej pamięci w stercie.
Przykład:
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.
źródło