Garbage collection (GC, po polsku odśmiecanie pamięci) to automatyczny mechanizm, który sam wyszukuje dane niepotrzebne już programowi i zwalnia zajmowaną przez nie pamięć. Zamiast ręcznie pilnować, kiedy zwolnić każdy kawałek pamięci, oddajesz tę robotę środowisku uruchomieniowemu (runtime). Korzystają z tego m.in. Java, C#, Go, Python, JavaScript czy Ruby.
Jak to działa
GC działa na prostym założeniu: jeśli do jakiegoś obiektu nie da się już dotrzeć z aktywnej części programu (zmiennych, stosu, pól statycznych), to znaczy, że nikt go nie używa i można go usunąć. Takie obiekty nazywamy nieosiągalnymi (unreachable). Klasyczny algorytm mark-and-sweep najpierw oznacza wszystko, co jest osiągalne, a potem zamiata resztę. Nowsze podejścia, jak generational GC, korzystają z obserwacji, że większość obiektów umiera młodo — więc dzielą pamięć na pokolenia i częściej sprzątają to świeże.
Dzięki temu nie musisz pamiętać o free() jak w C, a cała klasa błędów — wycieki pamięci po zapomnianym zwolnieniu, podwójne zwolnienie, dostęp do zwolnionej pamięci (use-after-free) — w dużej mierze znika. Cena? GC bywa nieprzewidywalne czasowo i potrafi na chwilę zatrzymać aplikację.
Przykład z praktyki
W JVM (Java) domyślnym garbage collectorem od Javy 9 jest G1GC. Możesz podejrzeć, co się dzieje z pamięcią, włączając logi GC przy starcie aplikacji:
java -Xlog:gc -jar mojaapka.jar
W logach zobaczysz pauzy typu „GC pause”, ich długość i ile pamięci odzyskano. Jeśli pauzy są za długie i psują responsywność, możesz przełączyć się na kolektor o niskich opóźnieniach, np. ZGC, dodając -XX:+UseZGC. W Pythonie z kolei masz hybrydę: liczenie referencji (reference counting) plus dodatkowy GC łapiący cykle — ręcznie odpalisz go przez gc.collect().
Częste mity i pułapki
Mit: „GC = brak wycieków pamięci”. Nieprawda. Jeśli trzymasz referencję do obiektu, którego już nie potrzebujesz (np. rosnąca w nieskończoność lista albo statyczna mapa cache), GC uzna go za potrzebny i nigdy nie zwolni. To wyciek logiczny — i potrafi przewrócić serwer.
Mit: „Wywołam GC ręcznie i będzie szybciej”. W Javie System.gc() to tylko sugestia, którą JVM zwykle ignoruje lub traktuje opieszale. Wymuszanie GC częściej szkodzi, niż pomaga. Uważaj też na pauzy „stop-the-world” w aplikacjach czasu rzeczywistego — tam czasem świadomie wybiera się języki bez GC.
Pojęcia powiązane: zarządzanie pamięcią, sterta (heap), stos (stack), wyciek pamięci, reference counting, mark-and-sweep, generational GC, RAII i ownership (model bez GC z Rusta/C++).