Java. Pytania rekrutacyjne dla Juniora: Zarządzanie pamięcią w Javie. Czyli co to jest garbage collector?

Gdzie przechowywane są zmienne i obiekty w Javie?

Chyba każdy kto czyta ten wpis musiał słyszeć określenie garbage collector. Wiedza o tym jak działa „śmieciarz” jest jedną z fundamentalnych przy pracy z Javą i często pojawia się na rozmowach rekrutacyjnych. Jednak zacznijmy od początku.

W Javie za zarządzanie pamięcią odpowiada wirtualna maszyna, czyli JVM (ang. Java Virtual Machine). Wyręcza ona w tym zakresie programistę, który nie musi przejmować się czyszczeniem pamięci. JVM wykorzystuje ów garbage collector do zwalniania pamięci, a konkretnie do usuwania obiektów, które nie mają przypisanych referencji.

Gdzie dokładnie znajdują się te tworzone obiekty? Warto zapamiętać, że obiekty tworzone są na stercie (ang. heap). To też jedno z częstych pytań, które może zadać rekruter. Obiekty więc przechowywane są na stercie, a nie na stosie (ang. stack). Stos bowiem przechowuje z jednej strony zmienne typów prostych (czyli inty, booleany, double itd.), a z drugiej referencje do obiektów utworznych na stercie. Jak pewnie domyślasz się stos (przechowujący tylko typy proste i referencje) zajmuje mniej pamięci niż sterta.

Spójrz na poniższy przykład, by dokładnie zrozumieć co dzieje się na stercie i stosie:

static void bla() {
    int a = 0;
    Object b = 0;
    Object c = a;
    Object d = b;
}

Co z powyższego znajdzie się na stercie, a co na stosie? Z pewnością nie mamy wątpliwości, że zmienna a trafi na stos, gdyż właśnie tam są przechowywane zmienne typów prostych. Natomiast obiekt b zostanie utworzony na stercie, gdyż tam są tworzone nowe obiekty. Co jednak z obiektem c? Jest on przecież referencją do zmiennej. Jak już wspomniałem referencje trafiają na stertę, ale do czego odnosi się ta referencja? W tym przypadku następuje opakowanie typu prostego w obiekt (autoboxing) i zamiast typu prostego mamy tu referencję do obiektu klasy Integer. Czy w takim razie obiekt c jest innym obiektem niż b, skoro mają tę samą wartość? Otóż nie. Jeżeli kojarzycie zasadę działania String Pool to może pamiętacie, że łańcuchy o tej samej wartości są przeważnie przechowane jako jeden obiekt by wlaśnie oszczędzić pamięć. W przypadku Integerów nie ma puli, ale pewne wartości są z góry dostępne. Tym samym tworząc różne obiekty o wartości 0 tak naprawdę dopisujemy referencję do już istniejącego obiektu. Tak się dzieje w zakresie -128 do 127. Więc porównanie a == b zwróci nam true:

static void bla() {
    int a = 0;
    Object b = 0;
    Object c = a;
    Object d = b;
    System.out.println(b == c); // true

    Object e = 128;
    Object f = 128;
    System.out.println(e == f); // false
}

Gdybyśmy chcieli wypisać adresy obiektów, to uzyskalibyśmy taki wynik wypisany na konsoli:

Obiekt b: java.lang.Integer@6f496d9f
Obiekt c: java.lang.Integer@6f496d9f
Obiekt d: java.lang.Integer@6f496d9f
Obiekt e: java.lang.Integer@506e1b77
Obiekt f: java.lang.Integer@4fca772d

Za co odpowiada garbage collector?

Co jednak robi ten słynny garbage collector? Jak widać stworzenie obiektu ma tak naprawdę dwie konsekwencje. Umieszczenie obiektu na stercie i przypisanie mu referencji na stosie. Gdy dana metoda skończy swoje działanie, to stos przestaje przechowywać jej zmienne i referencje. Garbage collector ma za zadanie usuwać takie obiekty ze sterty, które nie mają już żadnej referencji na stosie.

Myślę, że z niniejszego wpisu warto zapamiętać przede wszystkim to, że:

  • obiekty tworzone są na stercie (heap space);
  • zmienne typów prosty zapisywane są na stosie (stack memory);
  • na stosie przechowywane są referencje do obiektów na stercie
  • garbage collector czyści obiekty ze sterty, gdy znika do nich referencja

Jeżeli macie uwagi bądź pytania, piszcie w komentarzach.

Java. Pytania rekrutacyjne dla Juniora: Zarządzanie pamięcią w Javie. Czyli co to jest garbage collector?

Dodaj komentarz

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

Przewiń do góry