„Cześć! Postanowiłem dać ci kolejną małą lekcję na temat segregacji śmieci”.

Jak już wiesz, maszyna Java sama monitoruje, kiedy obiekt staje się niepotrzebny i usuwa go.

"Tak. Ty i Rishi mówiliście mi o tym wcześniej. Nie pamiętam szczegółów."

„OK. W takim razie przejrzyjmy to jeszcze raz”.

Zbiórka śmieci - 1

„Gdy tylko obiekt zostanie utworzony, JVM przydziela mu pamięć. Zainteresowanie obiektem jest monitorowane za pomocą zmiennych referencyjnych.  Obiekt można usunąć podczas wyrzucania elementów bezużytecznych, czyli procedury zwalniania pamięci, jeśli nie ma zmiennych odwołujących się do obiekt .

„Opowiedz mi trochę o śmieciarce — co to jest i jak działa”.

„OK. Wyrzucanie śmieci odbywało się w głównym wątku. Co 5 minut lub częściej. Jeśli kiedykolwiek było za mało wolnej pamięci, maszyna Java zawieszała wszystkie wątki i usuwała nieużywane obiekty”.

„Ale to podejście zostało teraz porzucone. Moduł wyrzucania elementów bezużytecznych nowej generacji działa za kulisami i na osobnym wątku. Nazywa się to współbieżnym wyrzucaniem elementów bezużytecznych”.

„Rozumiem. Jak dokładnie jest podejmowana decyzja o usunięciu obiektu lub nie?”

„Samo zliczanie liczby odniesień do obiektu nie jest zbyt efektywne — mogą istnieć obiekty, które odwołują się do siebie nawzajem, ale nie ma do nich odniesień żadne inne obiekty”.

„Tak więc Java przyjmuje inne podejście.  Java dzieli obiekty na osiągalne i nieosiągalne.  Obiekt jest osiągalny (żywy), jeśli odwołuje się do niego inny osiągalny (żywy) obiekt. Osiągalność jest określana na podstawie wątków. Uruchomione wątki są zawsze uważane za osiągalne (aktywne) , nawet jeśli nikt się do nich nie odwołuje”.

„OK. Myślę, że rozumiem”.

„Jak odbywa się rzeczywiste wyrzucanie elementów bezużytecznych — usuwanie niepotrzebnych obiektów?”

„To proste. W Javie pamięć jest podzielona na dwie części zgodnie z konwencją, a kiedy przychodzi czas na wyrzucanie elementów bezużytecznych, wszystkie żywe (osiągalne) obiekty są kopiowane do innej części pamięci, a cała stara pamięć jest zwalniana”.

„To ciekawe podejście. Nie ma potrzeby liczenia referencji: skopiuj wszystkie osiągalne obiekty, a wszystko inne to śmieci”.

„To trochę bardziej skomplikowane. Programiści Javy odkryli, że obiekty zazwyczaj dzielą się na dwie kategorie: długowieczne (które istnieją przez cały czas działania programu) i krótkotrwałe (które są potrzebne w metodach i do wykonywania „lokalnych » operacje)."

„O wiele bardziej efektywne jest oddzielenie obiektów długowiecznych od tych krótkotrwałych. Aby to zrobić, konieczne było znalezienie sposobu na określenie długowieczności obiektu”.

„Więc podzielili całą pamięć na «generacje». Istnieją obiekty pierwszej generacji, obiekty drugiej generacji itd. Za każdym razem, gdy pamięć jest czyszczona, licznik generacji jest zwiększany o 1. Jeśli pewne obiekty istnieją w wielu generacjach, to są rejestrowane jako długowieczne”.

„Dzisiaj Garbage Collector jest bardzo złożoną i wydajną częścią Javy. Wiele jego części działa heurystycznie — w oparciu o algorytmy, które zgadują. W rezultacie często «nie słucha» użytkownika”.

"Oznaczający?"

„Java ma obiekt wyrzucania elementów bezużytecznych ( GC ), który można wywołać przy użyciu metody System.gc ()”.

„Możesz także użyć System.runFinalization() do wymuszenia wywołań metod finalize obiektów, które mają zostać usunięte. Ale faktem jest, że zgodnie z dokumentacją Java nie gwarantuje to ani rozpoczęcia wyrzucania elementów bezużytecznych, ani finalizacji ( ) zostanie wywołana metoda.  Garbage collector decyduje, kiedy ją wywołać i na czym .

Dobrze wiedzieć.

„Ale to nie wszystko. Jak wiesz, w Javie niektóre obiekty odwołują się do innych. Ta sieć odniesień służy do określenia, czy obiekt powinien zostać usunięty”.

„I spójrz. Java ma specjalne referencje, które pozwalają ci wpływać na ten proces. Są dla nich specjalne klasy opakowujące. Oto one:”

SoftReference  to miękka referencja”.

WeakReference  to słabe odniesienie”.

PhantomReference to fantomowe odniesienie”.

„Uch… To przypomina mi klasy wewnętrzne, klasy zagnieżdżone, zagnieżdżone klasy anonimowe i klasy lokalne. Nazwy są różne, ale wcale nie jest jasne, do czego służą”.

„Powiedz, Amigo, że zostałeś programistą. Teraz jesteś zły z powodu nazw klas, mówiąc: «nie są wystarczająco informacyjne i nie można za pomocą jednej nazwy (!) określić, co ta klasa robi, jak, i dlaczego"."

„Wow. Nawet nie zauważyłem. Ale to takie oczywiste”.

"OK. Dość słów. Opowiem ci o SoftReferences."

„Te odniesienia zostały specjalnie zaprojektowane do buforowania, chociaż można ich używać do innych celów — wszystko według uznania programisty”.

„Oto przykład takiego odniesienia:”

Przykład
// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

„Jeśli jedyne odniesienia do obiektu są miękkie, to nadal żyje i jest nazywany„ miękko osiągalny ”.

„Ale!  Obiekt, do którego odwołują się tylko miękkie odniesienia, może zostać usunięty przez moduł wyrzucania elementów bezużytecznych, jeśli program nie ma wystarczającej ilości pamięci.  Jeśli nagle program nie ma wystarczającej ilości pamięci, przed rzuceniem wyjątku OutOfMemoryException , moduł wyrzucania elementów bezużytecznych usunie wszystkie obiekty do którego odwołują się miękkie odwołania i spróbuje ponownie przydzielić programowi pamięć."

„Załóżmy, że program kliencki często żąda różnych danych od programu serwera. Program serwera może użyć SoftReference do buforowania niektórych z nich. Jeśli obiekty chronione przed śmiercią przez miękkie referencje zajmują dużą część pamięci, moduł wyrzucania elementów bezużytecznych po prostu je usuwa wszystko. To jest piękne!

- Tak. Sam to lubiłem.

„Cóż, jeden mały dodatek: Klasa SoftReference ma dwie metody. Metoda get() zwraca obiekt, do którego odwołuje się SoftReference . Jeśli obiekt został usunięty przez moduł wyrzucania elementów bezużytecznych, metoda get () nagle zacznie zwracać wartość null”.

„Użytkownik może również jawnie wyczyścić SoftReference , wywołując metodę clear(). W takim przypadku słabe łącze wewnątrz obiektu SoftReference zostanie zniszczone”.

"To wszystko na teraz."

„Dzięki za interesującą historię, Ellie. To było naprawdę bardzo interesujące”.