kalendarz 23 lutego 2026 r.
🧹 Garbage Collector w Javie – jak naprawdę działa automatyczne sprzątanie pamięci?

🧹 Garbage Collector w Javie – jak naprawdę działa automatyczne sprzątanie pamięci?

kategorie: Garbage Collector Java
autor: Maciej Sobieniak

Programując w Java nie zwalniasz pamięci ręcznie. Nie wywołujesz free(), nie martwisz się o wskaźniki. A jednak aplikacja działa stabilnie, obiekty znikają, a pamięć się nie „zapcha”.

Za kulisami pracuje Garbage Collector (GC) – mechanizm automatycznego zarządzania pamięcią w ramach Java Virtual Machine (JVM).

Co to właściwie jest i jak działa. Postaram się po krótce wyjaśnić Ci to w poniższym wpisie.

1. Jak JVM zarządza pamięcią?

Z perspektywy GC najważniejsze są dwa obszary:

🔹 Stack (stos)

  • przechowuje zmienne lokalne i wywołania metod

  • działa szybko i jest czyszczony automatycznie po zakończeniu metody

  • GC się nim nie zajmuje

🔹 Heap (sterta)

  • tutaj trafiają wszystkie obiekty tworzone przez new

  • to właśnie ten obszar analizuje i czyści Garbage Collector


2. Kiedy obiekt może zostać usunięty?

Obiekt nadaje się do usunięcia, gdy:

  • nie ma do niego żadnej referencji

  • nie jest osiągalny z tzw. GC Roots


3. Co to jest GC Roots – punkty startowe analizy?

GC rozpoczyna przeszukiwanie od:

  • aktywnych wątków

  • zmiennych lokalnych na stosie

  • statycznych pól klas

  • referencji JNI

Jeżeli od żadnego z tych punktów nie prowadzi ścieżka do obiektu – staje się on kandydatem do usunięcia.


4. Jak działa algorytm Garbage Collectora?

Klasyczny model to:

🟢 Mark (oznaczanie)

GC przechodzi graf obiektów od GC Roots i oznacza wszystkie osiągalne.

🔴 Sweep (usuwanie)

Obiekty nieoznaczone są usuwane z pamięci.

🔵 Compact (kompaktowanie)

Pamięć jest porządkowana, aby zmniejszyć fragmentację.

Nowoczesne collectory stosują bardziej zaawansowane warianty, ale zasada pozostaje podobna.


4️. Generacyjny model pamięci – dlaczego to działa?

Empiryczna obserwacja:

Większość obiektów żyje bardzo krótko.

Dlatego heap podzielono na generacje:

🟢 Young Generation - czyszczenie tej części jest szybkie i częste.

  • Eden - każdy nowy obiekt trafia właśnie tutaj

  • Survivor 0

  • Survivor 1

Jak już wspominałem wcześniej każdy nowy obiekt trafia do Eden. Gdy Eden się zapełni uruchamiany jest Minor GC.

Minor GC działa według następującego schematu:

  • zatrzymuje aplikację (krótka tzw. Stop The World pauza)
  • oznacza obiekty osiągalne
  • kopiuje przeżywające obiekty do Survivor

Każdorazowe przeżycie obiektu powoduje zwiększenie jego licznika (licznik oznacza ile razy obiekt przeżył Minor GC). Po przekroczeniu przez obiekt określonego progu trafia on do Old Generation. 

Zapewnie zapytasz teraz do czego służa Survivor 0 oraz Survivor 1. Juz spieszę z wyjaśnieniami:

Obszary Survivor tworzą mechanizm rotacyjny stosowany po każdym Minor GC. Jeden jest źródłem, a drugi celem kopiowania. Przy następnym Minor GC role się odwracają. Ten proces zapobiega fragmentacji.

Kiedy obiekty trafiają do Old Generation:

  • gdy obiekt osiągnie odpowiedni licznik przeżyć Minor GC
  • gdy Survivor jest zbyt mały
  • w innych przypadkach, gdy GC uzna, że warto go przenieść

🔵 Old Generation

Obiekty, które przetrwały kilka cykli Minor GC.
Czyszczenie tej przestrzeni to Major GC – rzadsze, ale bardziej kosztowne ze względu na potrzebę przeanalizowania wiekszej ilości danych, relacji między obiektami oraz referencji.

⚫ Metaspace

Od Java 8 przechowuje metadane klas (wcześniej PermGen).


5️. Rodzaje Garbage Collectorów

Współczesna Java oferuje kilka implementacji GC.

🔹 Serial GC

  • jeden wątek

  • dobre rozwiązanie dla małych aplikacji

🔹 Parallel GC

  • wielowątkowy

  • nastawiony na maksymalną przepustowość

🔹 G1 GC (Garbage First)

  • dzieli heap na regiony

  • czyści najbardziej „opłacalne” obszary

  • domyślny w wielu wersjach Javy

🔹 ZGC

  • bardzo krótkie pauzy (nawet przy dużych heapach)

  • odpowiedni dla systemów o niskiej tolerancji opóźnień

🔹 Shenandoah

  • minimalizacja czasu „Stop The World”

  • równoległa kompaktacja


6️. Stop-The-World – czy GC zatrzymuje aplikację?

Tak, w niektórych fazach.

Podczas tzw. STW pause wszystkie wątki aplikacji są wstrzymywane.
Nowoczesne GC (np. G1 czy ZGC) redukują czas tych pauz do minimum.


7️. Referencje specjalne – zaawansowane zarządzanie pamięcią

Java udostępnia kilka typów referencji:

Typ referencji Kiedy usuwany obiekt? Zastosowanie
Strong Nigdy, dopóki istnieje referencja Standardowe użycie
WeakReference Przy kolejnym GC Mapy cache
SoftReference Przy braku pamięci Cache obrazów
PhantomReference Po finalizacji Zaawansowane zarządzanie zasobami

8️. Czy można ręcznie wywołać GC?

System.gc();

To tylko sugestia dla JVM.
Nie ma gwarancji natychmiastowego wykonania.

W aplikacjach produkcyjnych lepiej unikać takiego podejścia.


9️. Najczęstsze błędy prowadzące do problemów z pamięcią

❌ Statyczne kolekcje jako cache

static List<Object> cache = new ArrayList<>();

Obiekty mogą nigdy nie zostać usunięte.


❌ Niezamykane zasoby (np. strumienie)

Tu GC nie pomoże – należy używać try-with-resources.


❌ Memory leak przez listenery i callbacki

Brak wyrejestrowania powoduje utrzymywanie referencji.


❌ Tworzenie dużych obiektów w pętlach

Może prowadzić do częstych Minor GC i spadku wydajności.


10. GC w praktyce – konfiguracja JVM

Przykładowe flagi:

-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Xms512m -Xmx2g

Dla aplikacji opartych o Spring Framework odpowiednia konfiguracja GC może znacząco poprawić stabilność przy dużym obciążeniu.


11. Podsumowanie

Garbage Collector w Javie to:

✔ analiza grafu obiektów
✔ generacyjny model zarządzania pamięcią
✔ kompromis między wydajnością a czasem pauzy
✔ mechanizm, który znacząco zwiększa bezpieczeństwo aplikacji

Zrozumienie działania GC to moment, w którym przestajesz być „użytkownikiem Javy”, a zaczynasz świadomie pracować z JVM. Zrozumienie generacyjnego modelu pozwala:

✔ pisać kody przyjazny GC
✔ unikać dużych alokacji w pętlach
✔ projektować cache swiadomie
✔ sprawnie diagnozować problemy wydajnościowe

Komentarze (0)

Nie dodano jeszcze żadnych komentarzy

Odpowiadasz na komentarz:

Dodany:

Dodaj nowy komentarz:

Podobne atykuły, które mogą Cię zainteresować:

Lista wszystkich kolekcji

Lista kolekcji i interfejsów

W ramach powtórki poniżej przedstawiam wam listę kolekcji i interfejsów oraz wyjaśnię jak działa proces iteracji po elementach Set i Map, które nia maja określonego porzadku …

Cykl życia obiektu w Javie – od narodzin do sprzątania pamięci

Na pierwszy rzut oka obiekt w Javie wydaje się czymś prostym: tworzysz go, używasz i… zapominasz. W praktyce jednak każdy obiekt przechodzi kilka wyraźnych etapów, a ich zrozumienie pomogło mi …

Konstruktory w Javie – jak i po co tworzymy obiekty?

W Javie obiekty nie pojawiają się znikąd. Zanim zaczną „żyć” w pamięci programu, muszą zostać poprawnie zainicjalizowane. Właśnie w tym momencie do gry wchodzą konstruktory – specjalne metody odpowiedzialne …

== czy equals()? Jak poprawnie porównywać Stringi w Javie

Porównywanie napisów w Javie to jeden z tych tematów, które na pierwszy rzut oka wydają się banalne. W praktyce jednak bardzo często prowadzą do nieoczekiwanych wyników i trudnych do znalezienia …

Menu
Wykorzystuje pliki cookies!

Informuję, że stosuję pliki cookies - w celach statycznych, reklamowych oraz przystosowania serwisu do indywidualnych potrzeb użytkowników.
Są one zapisywane w Twoim urządzeniu końcowym. Można zablokować zapisywanie cookies, zmieniając ustawienia przeglądarki internetowej.