Przeczytałem ten artykuł na ten temat, ale tak naprawdę go nie rozumiem. Proszę o kilka porad wraz z przykładami przy opisywaniu pojęć.
Przeczytałem ten artykuł na ten temat, ale tak naprawdę go nie rozumiem. Proszę o kilka porad wraz z przykładami przy opisywaniu pojęć.
Odpowiedzi:
Java udostępnia dwa różne typy / klasy obiektów referencyjnych : mocne i słabe . Słabe obiekty odniesienia można dalej podzielić na miękkie i pozorne .
Przejdźmy punkt po punkcie.
Silny obiekt referencyjny
StringBuilder builder = new StringBuilder();
Jest to domyślny typ / klasa obiektu odniesienia, jeśli nie określono inaczej: builder
jest silnym obiektem odniesienia. Ten rodzaj odwołania powoduje, że obiekt, do którego istnieje odwołanie, nie kwalifikuje się do GC. Oznacza to, że za każdym razem, gdy odwołuje się do obiektu łańcuch silnych obiektów referencyjnych , nie można go usunąć.
Słaby obiekt odniesienia
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
Słabe obiekty referencyjne nie są domyślnym typem / klasą obiektu referencyjnego i aby ich użyć, należy je wyraźnie określić, jak w powyższym przykładzie. Ten rodzaj odniesienia sprawia, że obiekt odniesienia kwalifikuje się do GC. Oznacza to, że w przypadku, gdy jedynym odniesieniem osiągalnym dla StringBuilder
obiektu w pamięci jest w rzeczywistości słabe odniesienie, wówczas GC może zebrać StringBuilder
obiekt bezużyteczny . Gdy obiekt w pamięci jest osiągalny tylko przez słabe obiekty referencyjne, automatycznie kwalifikuje się do GC.
Poziomy słabości
Można wymienić dwa różne poziomy słabości: miękki i fantomowy .
Miękkie obiekt odniesienia jest zasadniczo słabe odniesienia Obiekt, który pozostaje w pamięci nieco więcej: Zwykle jest on odporny na cykl GC aż do zaniku pamięci jest dostępny i nie ma ryzyka OutOfMemoryError
(w tym przypadku, może być usunięty).
Z drugiej strony, fantomowy obiekt referencyjny jest przydatny tylko po to, aby wiedzieć dokładnie, kiedy obiekt został skutecznie usunięty z pamięci: zwykle są one używane do naprawiania dziwnego zachowania finalize () odrodzenia / wskrzeszenia , ponieważ w rzeczywistości nie zwracają samego obiektu, ale tylko pomagać w śledzeniu obecności ich pamięci .
Słabe obiekty referencyjne są idealne do implementacji modułów pamięci podręcznej. W rzeczywistości rodzaj automatycznej eksmisji można zaimplementować, umożliwiając GC czyszczenie obszarów pamięci, gdy obiekty / wartości nie są już osiągalne przez silny łańcuch odwołań. Przykładem jest WeakHashMap zachowujący słabe klucze.
Słabe odniesienie:
Krótko mówiąc, słabe odniesienie to odniesienie, które nie jest wystarczająco silne, aby zmusić obiekt do pozostania w pamięci. Słabe referencje pozwalają wykorzystać zdolność garbage collectora do określenia osiągalności dla Ciebie, więc nie musisz tego robić samodzielnie.
Miękkie odniesienie:
Miękkie odniesienie jest dokładnie takie samo, jak słabe odniesienie, z tą różnicą, że rzadziej wyrzuca obiekt, do którego się odnosi. Obiekt, który jest tylko słabo osiągalny (najsilniejsze odniesienia do niego to WeakReferences) zostanie odrzucony w następnym cyklu usuwania elementów bezużytecznych, ale obiekt, który jest łatwo osiągalny, na ogół pozostanie w pobliżu przez jakiś czas.
Odniesienie do fantomu:
Odniesienie do fantomu jest zupełnie inne niż SoftReference lub WeakReference. Jego uchwyt na obiekcie jest tak słaby, że nie możesz nawet go pobrać - jego metoda get () zawsze zwraca wartość null. Jedynym zastosowaniem takiego odniesienia jest śledzenie, kiedy zostanie umieszczone w kolejce ReferenceQueue, ponieważ w tym momencie wiesz, że obiekt, na który wskazywał, jest martwy.
Ten tekst został pobrany z: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references
Prosta różnica między SoftReference
i WeakReference
jest dostarczana przez programistę Android .
Różnica między a SoftReference
i a WeakReference
to moment, w którym zapada decyzja o wyczyszczeniu i umieszczeniu odniesienia w kolejce:
SoftReference
Powinny być wyczyszczone i skolejkowany tak późno jak to możliwe, czyli w przypadku VM jest w niebezpieczeństwie wyczerpaniu pamięci.
A WeakReference
można wyczyścić i umieścić w kolejce, gdy tylko wiadomo, że zawiera słabe odniesienia.
Trzy terminy, których użyłeś, są głównie związane z uprawnieniem obiektu do pobierania elementów bezużytecznych.
Słabe odniesienie : Jest to odniesienie, które nie jest wystarczająco silne, aby zmusić obiekt do pozostania w pamięci. To kaprysy garbage collectora, żeby zebrać ten obiekt do wyrzucenia śmieci. Nie możesz zmusić tego GC, żeby go nie odebrał .
Miękkie odniesienie : To mniej więcej to samo, co słabe odniesienie. Ale można powiedzieć, że trzyma obiekt nieco mocniej niż słabe odniesienie z czyszczenia pamięci.
Jeśli moduł wyrzucania elementów bezużytecznych zbierze słabe odniesienie w pierwszym cyklu życia, zbierze miękkie odniesienie w następnym cyklu usuwania elementów bezużytecznych.
Silne odniesienie : Jest to przeciwieństwo dwóch powyższych rodzajów odniesień. Mniej lubią zbierać śmieci (przeważnie nigdy nie są zbierane).
Możesz skorzystać z następującego łącza, aby uzyskać więcej informacji:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
Ten artykuł może być bardzo pomocny w zrozumieniu silnych, miękkich, słabych i fantomowych odniesień.
Aby dać ci podsumowanie,
Jeśli masz silne odwołanie do obiektu, obiekt nigdy nie może zostać zebrany / odzyskany przez GC (Garbage Collector).
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 odwołania do obiektu (bez silnych odniesień), obiekt zostanie odzyskany przez GC tylko wtedy, gdy zabraknie pamięci JVM.
Tworzymy odniesienia pozorne do obiektu, aby śledzić, kiedy obiekt zostanie umieszczony w kolejce do ReferenceQueue
. Gdy już wiesz, że możesz przeprowadzić drobnoziarnistą finalizację. (To uchroniłoby cię przed przypadkowym wskrzeszeniem obiektu, ponieważ widmo-odniesienie nie daje ci odsyłacza). Proponuję przeczytać ten artykuł, aby uzyskać szczegółowe informacje na ten temat.
Możesz więc powiedzieć, że silne odniesienia mają najwyższą moc (nigdy nie mogą być zebrane przez GC)
Miękkie odwołania są potężniejsze niż słabe odwołania (ponieważ mogą uciec przed cyklem GC, dopóki JVM nie zabraknie pamięci)
Słabe odniesienia są nawet mniej wydajne niż odniesienia miękkie (ponieważ nie mogą uciec od żadnego cyklu GC i zostaną odzyskane, jeśli obiekt nie ma innego silnego odniesienia).
Restauracja Analogia
Teraz, jeśli jesteś silnym klientem (analogicznie do silnego odniesienia), to nawet jeśli do restauracji wejdzie nowy klient lub cokolwiek się dzieje, nigdy nie opuścisz swojego stołu (obszar pamięci na stercie). Kelner nie ma prawa mówić (ani nawet prosić) o opuszczenie restauracji.
Jeśli jesteś klientem miękkim (analogicznie do miękkiego odniesienia), to jeśli do restauracji wejdzie nowy klient, kelner nie poprosi Cię o opuszczenie stolika, chyba że nie ma już innego pustego stolika, który mógłby pomieścić nowego klienta. (Innymi słowy, kelner poprosi Cię o opuszczenie stołu tylko wtedy, gdy pojawi się nowy klient i nie ma już innego stolika dla tego nowego klienta)
Jeśli jesteś słabym klientem (analogicznie do słabego odniesienia), to kelner może (w dowolnym momencie) poprosić Cię o opuszczenie restauracji: P
4 stopnie odniesienia - Strong, Weak, Soft, Phantom
Strong - jest rodzajem odwołania, które powoduje, że obiekt, do którego istnieje odwołanie, nie kwalifikuje się do GC. klasy budowniczych. np. - StringBuilder
Słaby - to odniesienie, które kwalifikuje się do GC.
Soft - to rodzaj odniesienia, którego obiekt kwalifikuje się do GC, dopóki pamięć nie będzie dostępna. Najlepsze do pamięci podręcznej obrazów. Będzie je przechowywać, dopóki pamięć nie będzie dostępna.
Fantom - to rodzaj odniesienia, którego obiekt bezpośrednio kwalifikuje się do GC. Używane tylko, aby wiedzieć, kiedy obiekt jest usuwany z pamięci.
używa:
Umożliwia określenie, kiedy obiekt jest dokładnie usuwany z pamięci.
gdy
finalize()
metoda jest przeciążona, GC może nie nastąpić w odpowiednim czasie dla obiektów kwalifikujących się do GC z dwóch klas. Tak więc odniesienie do fantomu kwalifikuje je wcześniej do GCfinalize()
, dlatego możesz uzyskać OutOfMemoryErrors nawet wtedy, gdy większość sterty to śmieci.
Słabe referencje są idealne do implementacji modułów pamięci podręcznej.
Oto Twoje zwykłe odniesienia do obiektów, które codziennie kodujemy:
Employee emp = new Employee();
Zmienna „emp” zawiera silne odwołanie do obiektu pracownika, a obiekty, do których można dotrzeć za pośrednictwem dowolnego łańcucha silnych odniesień, nie kwalifikują się do czyszczenia pamięci. Zwykle tego chcesz, ale nie zawsze. Teraz przypuśćmy, że pobieramy wielu pracowników z bazy danych w kolekcji lub mapie i musimy regularnie wykonywać na nich dużo przetwarzania, więc aby zachować wydajność, będziemy przechowywać ich w pamięci podręcznej.
O ile jest to dobre, ale teraz potrzebujemy różnych danych i nie potrzebujemy tych obiektów pracowników, a do nich nie można się odwoływać z dowolnego miejsca poza pamięcią podręczną. Co powoduje wyciek pamięci, ponieważ te obiekty nie są używane, ale nadal nie kwalifikują się do czyszczenia pamięci i nie możemy usunąć tych obiektów z pamięci podręcznej, ponieważ nie mamy do nich odniesienia? Więc tutaj albo musimy ręcznie opróżnić całą pamięć podręczną, co jest żmudne, albo możemy użyć innych rodzajów referencji, np. Słabe referencje.
Słabe odniesienie nie przypina obiektu do pamięci i zostanie poddane GC w następnym cyklu GC, jeśli nie zostanie przywołane z innych odniesień. Możemy użyć klasy WeakReference, która jest dostarczana przez Javę, aby stworzyć powyższy rodzaj pamięci podręcznych, które nie będą przechowywać obiektów, do których nie istnieją odwołania z innych źródeł.
WeakReference<Cache> cache = new WeakReference<Cache>(data);
Aby uzyskać dostęp do danych, musisz wywołać cache.get (). To wywołanie get może zwrócić wartość null, jeśli słabe odniesienie zostało zebrane w pamięci: musisz sprawdzić zwracaną wartość, aby uniknąć NPE. Java udostępnia kolekcje, które używają słabych odniesień, np. Klasa WeakHashMap przechowuje klucze (nie wartości) jako słabe odwołania. Jeśli klucz jest oznaczony GC, wartość zostanie również automatycznie usunięta z mapy.
Ponieważ słabe odwołania są również obiektami, potrzebujemy sposobu, aby je wyczyścić (nie są już przydatne, gdy obiekt, do którego się odnosili, został poddany GC). Jeśli przekażesz ReferenceQueue do konstruktora dla słabego odwołania, moduł wyrzucania elementów bezużytecznych dołączy to słabe odwołanie do ReferenceQueue, zanim zostaną sfinalizowane lub poddane GC. Możesz okresowo przetwarzać tę kolejkę i radzić sobie z martwymi odwołaniami.
SoftReference jest podobny do WeakReference, ale jest mniej prawdopodobne, że zostanie wyrzucony jako śmieci. Miękkie odwołania są czyszczone według uznania modułu odśmiecania pamięci w odpowiedzi na zapotrzebowanie na pamięć. Maszyna wirtualna gwarantuje, że wszystkie miękkie odwołania do miękko dostępnych obiektów zostaną wyczyszczone, zanim wyrzuci ona błąd OutOfMemoryError.
Odwołania fantomowe są najsłabszymi ze wszystkich typów odwołań, wywołanie ich wywołania zawsze zwróci wartość null. Do obiektu odwołuje się fantom po jego sfinalizowaniu, ale przed odzyskaniem przydzielonej mu pamięci, w przeciwieństwie do słabych referencji, które są umieszczane w kolejce przed sfinalizowaniem lub referencje fantomowe GC są rzadko używane.
Jak więc są przydatne? Kiedy konstruujesz odniesienie do fantomu, musisz zawsze przekazać ReferenceQueue. Oznacza to, że możesz użyć odwołania pozornego, aby zobaczyć, kiedy obiekt jest oznaczony metodą GC.
Hej, więc jeśli słabe referencje są kolejkowane, gdy są uważane za sfinalizowane, ale jeszcze nie GC, moglibyśmy utworzyć nowe silne odniesienie do obiektu w bloku finalizatora i uniemożliwić GC obiektowi. Tak, możesz, ale prawdopodobnie nie powinieneś tego robić. Aby sprawdzić ten przypadek, cykl GC nastąpi co najmniej dwa razy dla każdego obiektu, chyba że obiekt ten jest osiągalny tylko przez odniesienie fantomowe. Dlatego możesz zabraknąć stosu, nawet jeśli twoja pamięć zawiera mnóstwo śmieci. Mogą temu zapobiec odniesienia fantomowe.
Więcej na ten temat przeczytasz w moim artykule Typy referencji w Javie (Strong, Soft, Weak, Phantom) .