CodeGym /Blog Java /Random-PL /Więcej o śmieciarce
Autor
Milan Vucic
Programming Tutor at Codementor.io

Więcej o śmieciarce

Opublikowano w grupie Random-PL
Cześć! Podczas ostatniej lekcji po raz pierwszy zapoznaliśmy się z wbudowanym w Javę modułem zbierania elementów bezużytecznych i mieliśmy ogólne pojęcie o tym, jak on działa. Działa w tle podczas działania programu, zbierając niepotrzebne obiekty, które później zostaną usunięte. W ten sposób zwalnia pamięć, którą można wykorzystać do tworzenia nowych obiektów w przyszłości.
Więcej o śmieciarzu - 1
W tej lekcji omówimy bardziej szczegółowo, jak to działa. Na przykład, jak i kiedy przedmiot staje się niepotrzebny? A jak śmieciarz się o tym dowie? Oto pytania, na które odpowiemy podczas dzisiejszej lekcji :) Lekcja będzie miała charakter przeglądu: nie musisz uczyć się tego materiału na pamięć. Intencją jest głównie poszerzenie swojej wizji dotyczącej działania pamięci i modułu zbierania elementów bezużytecznych, więc po prostu przeczytaj i znajdź coś nowego dla siebie :) Do dzieła! Pierwszą rzeczą, o której musisz pamiętać, jest to, że moduł wyrzucania elementów bezużytecznych działa równolegle z twoim programem. To nie jest częścią twojego programu. Działa oddzielnie (na ostatniej lekcji porównaliśmy to do robota odkurzającego). Ale nie zawsze tak było. Wyrzucanie elementów bezużytecznych odbywało się kiedyś w tym samym wątku co twój program. W pewnym harmonogramie (raz na kilka minut) moduł wyrzucania elementów bezużytecznych sprawdzałby obecność niepożądanych obiektów w programie. Problem polegał na tym, że program zawieszał się (nie wykonywał) podczas tego sprawdzania i wyrzucania elementów bezużytecznych. Wyobraź sobie, że siedzisz w swoim biurze w pracy. Ale wtedy przychodzi sprzątaczka, żeby umyć podłogi. Odciąga cię od komputera na 5 minut i czekasz, aż skończy sprzątać. W tym czasie nie możesz pracować. Tak mniej więcej działało Garbage Collection :) Później ten mechanizm został zmieniony i teraz Garbage Collector działa w tle, nie utrudniając pracy samego programu. Wiesz już, że obiekt umiera, gdy nie ma już odniesień. W rzeczywistości,moduł wyrzucania elementów bezużytecznych nie zlicza odwołań do obiektów . Po pierwsze, może to zająć dużo czasu. Po drugie, jest mało wydajny. W końcu przedmioty mogą się do siebie odnosić! Więcej o śmieciarzu - 2Rysunek pokazuje przykład, w którym 3 obiekty odnoszą się do siebie, ale nikt inny się do nich nie odnosi. Innymi słowy, reszta programu ich nie potrzebuje. Gdyby śmieciarz po prostu policzył referencje, te 3 obiekty nie zostałyby zebrane, a pamięć nie zostałaby zwolniona (są do nich referencje!). Możemy to porównać do statku kosmicznego. Podczas lotu astronauci postanawiają sprawdzić listę części zamiennych dostępnych do naprawy. Znajdują między innymi kierownicę i pedały ze zwykłego samochodu. Oczywiście nie są tu potrzebne i niepotrzebnie zajmują miejsce (chociaż te dwie części są ze sobą powiązane i pełnią pewne funkcje). Ale wewnątrz statku kosmicznego są bezużytecznymi śmieciami, które należy wyrzucić. W związku z tym w Javie podjęto decyzję o zbieraniu śmieci na podstawie liczenia referencji,osiągalne i nieosiągalne . Jak określić, czy obiekt jest osiągalny? To wszystko jest po prostu genialne. Obiekt jest osiągalny, jeśli odwołuje się do niego inny osiągalny obiekt. W ten sposób otrzymujemy „łańcuch osiągalności”. Rozpoczyna się wraz z uruchomieniem programu i trwa przez cały czas trwania programu. Wygląda to mniej więcej tak: Więcej o śmieciarzu - 3 Strzałka na rysunku wskazuje kod wykonywalny naszego programu. Kod (na przykład main()metoda) tworzy odwołania do obiektów. Te obiekty mogą odnosić się do innych obiektów, te obiekty do jeszcze innych i tak dalej. Tworzy to łańcuch odniesienia. Jeśli możesz prześledzić łańcuch od obiektu do „odniesienia głównego” (tego utworzonego bezpośrednio w kodzie wykonywalnym), wówczas jest to uważane za osiągalne. Takie obiekty są zaznaczone na rysunku kolorem czarnym. Ale obiekt jest nieosiągalny, jeśli wypadnie z tego łańcucha, tj. żadna ze zmiennych w aktualnie wykonywanym kodzie nie odwołuje się do niego i nie można do niego dotrzeć przez „łańcuch referencyjny”. W naszym programie na czerwono zaznaczono dwa takie obiekty. Zauważ, że te „czerwone” obiekty mają odniesienia do siebie. Ale jak powiedzieliśmy wcześniej, nowoczesny moduł wyrzucania elementów bezużytecznych w Javie nie zlicza referencji. Określa, czy obiekt jest osiągalny , czy nieosiągalny. W rezultacie zaczepi się o dwa czerwone obiekty na rysunku. Teraz spójrzmy na cały proces od początku do końca. W ten sposób zobaczymy również, jak zorganizowana jest pamięć w Javie :) Wszystkie obiekty Javy są przechowywane w specjalnym obszarze pamięci zwanym stertą . W języku potocznym kupa to zwykle góra przedmiotów, w której wszystko jest wymieszane. Ale to nie jest sterta w Javie. Jego struktura jest bardzo logiczna i rozsądna. W pewnym momencie programiści Java odkryli, że wszystkie ich obiekty można podzielić na dwa typy: obiekty proste i „obiekty długowieczne”. „Obiekty długowieczne” to obiekty, które przetrwały wiele rund zbierania śmieci. Zwykle żyją do końca programu. Ostatecznie pełna sterta, w której przechowywane są wszystkie obiekty, została podzielona na kilka części. Pierwsza część ma piękną nazwę: eden(z biblijnego „Ogrodu Eden”). Ta nazwa jest odpowiednia, ponieważ to tutaj kończą się obiekty po ich utworzeniu. Jest to część pamięci, w której tworzone są nowe obiekty, gdy używamy słowa kluczowego new. Można utworzyć wiele obiektów. Kiedy w tym obszarze zabraknie miejsca, rozpoczyna się początkowe „szybkie” wyrzucanie elementów bezużytecznych. Musimy powiedzieć, że śmieciarz jest bardzo sprytny. Wybiera algorytm na podstawie tego, czy sterta zawiera więcej śmieci, czy więcej żywych obiektów. Jeśli prawie wszystkie obiekty są śmieciami, kolektor oznacza aktywne obiekty i przenosi je do innego obszaru pamięci. Następnie bieżący obszar jest całkowicie wyczyszczony. Jeśli nie ma dużo śmieci, a sterta to głównie żywe obiekty, zbieracz oznacza śmieci, czyści je i pakuje razem inne obiekty. Powiedzieliśmy "przestrzeń przetrwania . Z kolei przestrzeń przetrwania dzieli się na generacje . Każdy obiekt należy do określonej generacji, w zależności od tego, ile rund wyrzucania elementów bezużytecznych przetrwał. Jeśli obiekt przetrwał jedną rundę wyrzucania elementów bezużytecznych, to znajduje się w „Generacji 1”; jeśli 5, to „Generacja 5”. Eden i przestrzeń przetrwania tworzą razem obszar zwany młodym pokoleniem . Oprócz młodego pokolenia sterta ma jeszcze jeden obszar pamięci zwany starą generacją. To jest dokładnie miejsce, w którym trafiają długowieczne przedmioty, które przetrwały wiele rund wywozu śmieci. Są zalety trzymania ich oddzielnie od wszystkich innych. Pełne wyrzucanie elementów bezużytecznych jest wykonywane tylko wtedy, gdy stara generacja jest pełna, tzn. w programie jest tak wiele długowiecznych obiektów, że brakuje pamięci. Ten proces obejmuje więcej niż jeden obszar pamięci. Ogólnie dotyczy to wszystkich obiektów tworzonych przez maszynę Java. Oczywiście wymaga to znacznie więcej czasu i zasobów. Właśnie dlatego podjęto decyzję o oddzielnym przechowywaniu przedmiotów długowiecznych. „Szybkie zbieranie śmieci” jest przeprowadzane, gdy w innych obszarach zabraknie miejsca. Dotyczy to tylko jednego obszaru, co czyni go szybszym i wydajniejszym. Wreszcie, kiedy nawet obszar dla obiektów długowiecznych jest całkowicie wypełniony, uruchamiane jest pełne wyrzucanie elementów bezużytecznych. Zatem zbieracz używa „najcięższego” narzędzia tylko wtedy, gdy nie można go uniknąć. Oto wizualna reprezentacja struktury sterty i wyrzucania elementów bezużytecznych: Więcej o śmieciarzu - 4
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION