Garbage Collector Javy 5/5

Heap of Fish: Symulacja

Aplet Heap of Fish przedstawiony na rysunkach 9-2 do 9-5 wykazuje kompaktowanie, zaznaczanie i zamiatanie odśmiecanej sterty. Aby ułatwić kompaktowanie, sterta ta używa pośrednich uchwytów do obiektów zamiast bezpośrednich odniesień. Nazywa się Heap of Fish ponieważ jedynym typem obiektów przechowywanych na stercie dla tej demonstracji są obiekty ryb określone w następujący sposób:

// Na CD-ROM w pliku gc/ex1/YellowFish.java
class YellowFish {

YellowFish myfriend;
}

// Na CD-ROM w pliku gc/ex1/BlueFish.java
class Bluefish {

Bluefish myfriend;
YellowFish myLunch;
}

// Na CD-ROM w pliku gc/ex1/RedFish.java
class RedFish {

RedFish myfriend;
Bluefish myLunch;
YellowFish mySnack;
}

Jak widać, istnieją trzy rodzaje ryb: czerwona, żółta i niebieska. Czerwona ryba jest największą ponieważ ma trzy zmienne instancji. Żółta ryba, tylko z jedną zmienną instancji, jest najmniejszą rybą. Blue Fish ma dwie zmienne instancji, a zatem jest średniej wielkości.
Zmienne instancji obiektów ryby mają odniesienia do innych obiektów ryb. BlueFish.myLunch, na przykład, jest odniesieniem do obiektu YellowFish. W implementacji odśmiecanej sterty odniesienie do obiektu zajmuje cztery bajty. W związku z tym wielkość danych instancji obiektu RedFish jest dwanaście bajtów, obiektu BlueFish jest osiem bajtów, a obiekt YellowFish ma cztery bajty.
Heap of Fish ma pięć trybów, które można wybrać za pomocą przycisków opcji w lewym dolnym rogu apletu. Kiedy aplet startuje, jest w trybie pływania. Tryb pływania jest tylko zbędną animacją, trochę przypomina znany obraz dużej ryby mającej zamiar zjeść średnią rybę mającą zamiar zjeść małą rybę. Pozostałe cztery tryby – alokowanie ryb, przypisanie referencji, zbieranie śmieci i kompaktowanie sterty – pozwalają na interakcję ze stertą. W trybie alokacji ryb, możesz utworzyć instancję nowych obiektów ryb. W trybie przypisywania odniesień można zbudować sieć lokalnych zmiennych i ryb, które odnoszą się do innych ryb. W trybie odśmiecania, operacje zaznaczania i wymiatania zwolnią rybę nie mającą referencji. Tryb kompaktowania sterty pozwala przesuwać obiekty sterty tak, że są one obok siebie na końcu sterty, zostawiając całą wolną pamięć jako jeden ciągły blok na drugim końcu sterty.

Alokacja Ryb

Tryb alokacji ryb pokazany na rys. 9-6 pozwala na przydzielanie nowych obiektów ryb na stercie. W tym trybie można zobaczyć dwie części, które składają się na stercie: pula obiektów i pula uchwytów. Pula obiektów jest ciągłym blokiem pamięci z którego jest brane miejsce dla nowych obiektów. Jest zorganizowana w postaci szeregu bloków pamięci. Każdy blok pamięci ma czterobajtowy nagłówek który określa długość bloku pamięci i czy jest wolny. Nagłówki są wyświetlane w aplecie jako czarne poziome linie w puli obiektów.


Rysunek 9-6. Tryb alokowania ryb apletuHeap of Fish.

Pula obiektów w Heap of Fish jest realizowana jako tablica liczb int. Pierwszy nagłówek jest zawsze w objectPool[0]. Seria pul obiektów bloków pamięci może być przesuwana przez przeskakiwanie z nagłówka do nagłówka. Każdy nagłówek daje długość jego bloku pamięci, który pokazuje również gdzie będzie następny nagłówek. Nagłówek następnego bloku pamięci będzie pierwszym int bezpośrednio następującym po bieżącym bloku pamięci.
Gdy jest alokowany nowy obiekt, przemierzana jest pula obiektów dotąd aż blok pamięci ma wyliczone wystarczająco dużo miejsca aby pomieścić nowy obiekt. Przydzielone obiekty w puli obiektów są wyświetlane w postaci kolorowych pasków. Obiekty YellowFish są wyświetlane na żółto, BlueFish w kolorze niebieskim a RedFish w czerwonym. Wolne bloki pamięci, które obecnie nie zawierają ryb, pokazane są w kolorze białym.
Pula uchwytów w Heap of Fish jest zaimplementowana jako tablica obiektów klasy o nazwie ObjectHandle . ObjectHandle zawiera informacje na temat obiektu, w tym istotny indeks do tablicy puli obiektów. Ten indeks jest referencją do danych wystąpienia obiektu w puli obiektów. ObjectHandle pokazuje również informacje o klasie obiektu ryb. Jak wspomniano w rozdziale 5 “The Java Virtual Machine”, każdy obiekt na stercie musi być w jakiś sposób związany z jej klasą informacji przechowywanych w obszarze metody. W Heap of Fish ObjectHandle łączy każdy przydzielony obiekt z informacją taką jak jego klasa – czy jest to RedFish , BlueFish lub YellowFish – a niektóre dane używany do wyświetlania ryb w interfejsie użytkownika apletu.
Pula uchwytów istnieje aby ułatwić do defragmentację puli obiektów z powodu kompaktowania. Odwołania do obiektów, które mogą być przechowywane w zmiennych lokalnych stosu lub zmienne instancji innych obiektów, nie są bezpośrednio indeksowane na tablicę puli obiektów. Są zamiast tego indeksowane na tablicę puli uchwytów. Gdy obiekty w puli obiektów są przenoszone do kompaktowania, tylko odpowiedni ObjectHandle musi być zaktualizowany na nowy indeks tablicy puli obiektów.
Każdy uchwyt w puli uchwytów który odnosi się do obiektu ryby jest pokazany jako poziomy pasek rysowany w takim kolorze jak ryba do której się odnosi. Linia łączy każdy uchwyt do ich zmiennych instancji ryb w puli obiektów. Te uchwyty które nie są obecnie w użyciu są rysowane w kolorze białym.

Przypisywanie Referencji

Tryb przypisywania referencji przedstawione na rys. 9-7 pozwala zbudować sieć odniesień między zmiennymi lokalnymi a przydzielonymi obiektami ryb. Referencja jest po prostu lokalną lub instancyjna zmienną która zawiera ważne odniesienie do obiektu. Są trzy zmienne lokalne, które służą jako korzenie odśmiecania, po jednej dla każdego rodzaju ryby. Jeśli nie połączymy żadnej ryby ze zmiennymi lokalnymi, to wszystkie ryby zostaną uznane za nieosiągalne i uwolnione przez garbage collector.


Rysunek 9-7. Tryb przypisywania referencji apletu Heap of Fish.

Tryb przypisywania referencji posiada trzy podtryby: przenoszenie ryby, dołączenie i odłączenie ryby. Można wybrać podtryb za pomocą radiobuttonów w dolnej części płótna na którym pojawiają się ryby. W trybie przenoszenia ryb możesz kliknąć na rybę i przeciągnąć ją w nowe miejsce. Możesz chcieć to zrobić aby linki były bardziej widoczne lub po prostu masz ochotę na przeorganizowanie ryb w morzu.
W trybie łączenia ryb możesz kliknąć na rybę lub zmienną lokalną i przeciągnąć link do innej ryby. Rybie lub zmiennej lokalnej którą na początku przeciągnąłeś zostanie przydzielona referencja do ryby którą ostatecznie upuściłeś. Pojawi się linia łącząca dwa elementy. Linia łącząca dwie ryby zostanie nakreślona pomiędzy nosem ryby z referencją a ogonem ryb do której się odwołuje.
Klasa YellowFish ma tylko jedną zmienną instancyjną, myFriend, która jest odniesieniem do obiektu YellowFish. Dlatego żółta ryba może być powiązana wyłącznie z inną żółtą rybą. Kiedy połączysz dwie żółte ryby, zmiennej myFriend “wyciąganej z” ryby będzie przypisane odniesienie do “upuszczonej na” ryby. Jeśli akcja zostały zaimplementowane w kodzie Java, może to wyglądać tak:

// Przydzielane są gdzieś Fish
YellowFish draggedFromFish = new YellowFish ();
YellowFish droppedUponFish = new YellowFish ();

// Jakiś czas później przypisanie odbywa się
draggedFromFish.myFriend = droppedUponFish;

Klasa BlueFish ma dwie zmienne instancyjne, BlueFish myFriend i YellowFish myLunch . Dlatego niebieska ryba może być powiązana z jedną niebieską rybą i jedną rybą żółtą. Klasa RedFish ma trzy zmienne instancyjne, RedFish myFriend , BlueFish myLunch i YellowFish mySnack . Czerwone ryby można zatem łączyć z jednym wystąpieniem każdego rodzaju ryby.
W trybie odłączania ryb można odłączyć ryby przesuwając kursor nad linią łączącą dwie ryby. Gdy kursor jest na linii, linia będzie czarna. Po kliknięciu na czarną linię referencja zostanie ustawiona na null i linia zniknie.

Odśmiecanie

Tryb zbierania śmieci pokazany na rysunku 9-8 pozwala na prowadzenie algorytmu zaznaczania i wymiatania. Przycisk Step na dole płótna przeprowadzi cię przez proces odśmiecania jeden krok na raz. Możesz zresetować garbage collector w dowolnym momencie klikając przycisk Reset. Jednak gdy garbage collector zamiótł, zwolnienie ryb jest nieodwracalne. Nie sposób gorączkowo klikając na przycisk Reset przywrócić je z powrotem.


Rysunek 9-8. Tryb zbierania śmieci apletu Heap of Fish.

Proces odśmiecania jest podzielony na fazę oznaczania i fazę wymiatania. Podczas fazy oznaczania, obiekty ryb na stercie pokonywane są wgłąb zaczynając od zmiennych lokalnych. Podczas fazy wymiatania, wszystkie nieoznakowane obiekty ryb są zwalniane.
Na początku fazy oznaczania, wszystkie zmienne lokalne, ryby i linki są wyświetlane w kolorze białym. Każde naciśnięcie przycisku Step posuwa naprzód przechodzenie wgłąb jednego węzła. Bieżący węzeł przeglądania jak też lokalna zmienna lub ryba wyświetlane są na amarantowo. Gdy garbage collector przechodzi w dół gałęzi, ryby wzdłuż gałęzi zmieniane są z białego na szary. Szary oznacza ryby które zostały osiągnięte przez przeglądanie ale mogą być dalsze ryby w dole gałęzi które nie zostały osiągnięte. Gdy został osiągnięty końcowy węzeł, kolor końcowej ryby zmienia się na czarny i przeglądanie cofa się w górę gałęzi. Gdy wszystkie linki poniżej ryby zostały oznaczone czarny, ryba ta jest oznaczana jako czarna i przeglądanie wraca drogą którą przyszło.
Pod koniec fazy zaznaczania wszystkie osiągalne ryby mają kolor czarny a wszystkie nieosiągalne są białe. Faza zamiatania następnie zwalnia pamięć zajmowaną przez białe ryby.

Kompaktowanie sterty

Tryb kompaktowania sterty rys. 9-9, pozwala na przeniesienie jednego obiektu na raz do jednego końca puli obiektów. Każde naciśnięcie przycisku Slide przesunie jeden obiekt. Widać, że tylko te dane wystąpienia obiektu w puli obiektów przemieszczają się; uchwyt w puli uchwytów nie przemieszcza się.


Rysunek 9-9. Tryb kompaktowania sterty apletu Heap of Fish

Aplet Heap of Fish pozwala na przydzielanie nowych obiektów ryb, łączenie ryby, zbieranie śmieci i kompaktowanie sterty. Działania te mogą być wykonane w dowolnej kolejności, jak wolisz. Przez zabawę z apletem powinieneś być w stanie poznać dobrze ideę działania zaznaczania i zamiatania. Jest tekst na dole apletu który powinien Ci pomóc. Miłego klikania.

CD-ROM zawiera przykłady kodu źródłowego z tego działu w katalogu gc. Aplet Heap of Fish jest zawarty na stronie internetowej na CD-ROM w pliku applets/HeapOfFish.html . Kod źródłowy tego apletu znajduje się obok swojej klasie plików, w applets/HeapOfFish katalogu.

Zasoby strony

Więcej informacji na temat materiału prezentowanego w tym rozdziale można znaleźć na stronie zasobów: http://www.artima.com/insidejvm/resources/ .

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *