Referencje „słabe” i „miękkie” (WeakReference, SoftReference) zostały dodane do Java API już dawno, jednak nie każdy programista jest z nimi zaznajomiony. Wskazuje to na lukę w zrozumieniu, gdzie i jak z nich korzystać. Klasy referencyjne są szczególnie ważne w kontekście zbierania elementów bezużytecznych . Jak wszyscy wiemy, moduł zbierający elementy bezużyteczne sam zwalnia pamięć zajmowaną przez obiekty, jednak nie wszyscy programiści wiedzą, że decyzję o zwolnieniu pamięci podejmuje w oparciu o rodzaj dostępnych odniesień do obiektu. Główną różnicą między SoftReference i WeakReference jest sposób, w jaki kolektor będzie z nimi współpracował. Może w każdej chwili usunąć obiekt, jeśli wskażą na niego tylko słabe łącza, natomiast obiekty z miękkim łączem będą zbierane tylko wtedy, gdy JVM rzeczywiście będzie potrzebowała pamięci. Ze względu na te cechy klas referencyjnych, każda z nich ma swoje własne zastosowanie. SoftReference można wykorzystać do implementacji pamięci podręcznych, a gdy JVM będzie potrzebowała pamięci, zwolni ją, usuwając takie obiekty. A WeakReferences doskonale nadają się do przechowywania metadanych, na przykład przechowywania łącza do modułu ClassLoader. Jeśli nie ma klas do załadowania, nie ma sensu przechowywać odniesienia do ClassLoader , słabe odwołanie sprawia, że ClassLoader jest dostępny do usunięcia, gdy tylko go przypiszemy zamiast silnego odniesienia. W tym artykule przyjrzymy się różnicom między typami linków, w tym silnym odwołaniem i odwołaniem fantomowym .
WeakReference vs SoftReference w Javie
Dla tych, którzy nie wiedzą, istnieją 4 rodzaje linków:- Mocne odniesienie
- Słabe odniesienie
- Miękkie odniesienie
- Widmowe odniesienie
Counter counter = new Counter(); // strong reference
WeakReference weakCounter = new WeakReference(counter); //weak reference
counter = null; // now Counter object is eligible for garbage collection
Teraz, gdy ustawisz licznik silnych odwołań na wartość null (licznik = null), obiekt utworzony w pierwszym wierszu stanie się dostępny do zbierania elementów bezużytecznych, ponieważ nie ma już silnego odniesienia. Odwołanie słabeCounter utworzone przez Weak nie może uniemożliwić modułowi zbierającemu usunięcia obiektu Counter. Z drugiej strony, gdyby było to odniesienie Soft, obiekt Counter nie zostałby usunięty, dopóki maszyna JVM nie będzie szczególnie potrzebowała pamięci. Miękkie odwołania w Javie są reprezentowane przez klasę java.lang.ref.SoftReference . Przykład tworzenia SoftReference w Javie
Counter prime = new Counter(); // prime holds a strong reference
SoftReference soft = new SoftReference(prime) ; //soft reference variable has SoftReference to Counter Object
prime = null; // now Counter object is eligible for garbage collection but only be collected when JVM absolutely needs memory
Po wyczyszczeniu silnej referencji (w 3 linii) pozostanie tylko 1 miękka referencja do obiektu Counter, która nie będzie mogła zapobiec usunięciu tego obiektu przez śmieciarza, ale w odróżnieniu od słabej referencji będzie mogła odłożyć ten proces do momentu wystąpienia ostrego niedoboru pamięci. Biorąc pod uwagę tę różnicę między łączami miękkimi i słabymi, pierwsze jest bardziej odpowiednie dla pamięci podręcznych i słabe dla metadanych. Dobrym przykładem jest klasa WeakHashMap, która jest następcą interfejsu Map, takiego jak klasy HashMap lub TreeMap , ale ma jedną charakterystyczną cechę. WeakHashMap otacza klucze jako słabe referencje, co oznacza, że gdy nie ma silnych referencji do obiektu, słabe referencje znajdujące się wewnątrz WeakHashMap nie uchronią Cię przed modułem zbierającym elementy bezużyteczne. Linki fantomowe to trzeci typ linków dostępnych w pakiecie java.lang.ref. Odniesienia fantomowe są reprezentowane przez klasę java.lang.ref.PhantomReference . Obiekt, na który wskazują jedynie łącza fantomowe, może zostać w każdej chwili usunięty przez kolekcjonera. Połączenie fantomowe tworzy się w taki sam sposób, jak łącze słabe lub miękkie.
DigitalCounter digit = new DigitalCounter(); // digit reference variable has strong reference
PhantomReference phantom = new PhantomReference(digit); // phantom reference
digit = null;
Po wyczyszczeniu silnych odniesień do obiektu DigitalCounter moduł wyrzucania elementów bezużytecznych usunie go w dowolnym momencie, ponieważ teraz wskazują na niego tylko odniesienia fantomowe. Oprócz klas WeakReference, SoftReference, PhantomReference, WeakHashMap warto poznać klasę ReferenceQueue . Możesz użyć tej klasy podczas tworzenia obiektu WeakReference, SoftReference lub PhantomReference:
ReferenceQueue refQueue = new ReferenceQueue(); //reference will be stored in this queue for cleanup
DigitalCounter digit = new DigitalCounter();
PhantomReference phantom = new PhantomReference(digit, refQueue);
Odniesienie do obiektu zostanie dodane do kolejki referencyjnej i będzie można monitorować stan odniesień poprzez odpytywanie kolejki referencyjnej. Cykl życia obiektu dobrze przedstawiono na tym diagramie: Oto wszystkie różnice pomiędzy słabymi i miękkimi odniesieniami w Javie . Zapoznaliśmy się także z łączami fantomowymi, klasą WeakHashMap i ReferenceQueue . Właściwe użycie referencji pomoże w usuwaniu elementów bezużytecznych i spowoduje bardziej elastyczne zarządzanie pamięcią w Javie . Oryginalny artykuł
GO TO FULL VERSION