Как работает сборка мусора
GC освобождает память объектов, которые больше не достижимы от корней. JVM не считает ссылки; она обходит граф объектов.
Типичные GC roots:
- локальные переменные и параметры активных стеков;
- статические поля загруженных классов;
- активные потоки;
- JNI-ссылки и внутренние структуры JVM.
Node first = new Node();
Node second = new Node();
first.next = second;
second.next = first;
first = null;
second = null; // цикл недостижим и может быть собранЦиклические ссылки не мешают tracing collector: важен путь от GC root.
Основные операции
- mark — определить живые объекты;
- sweep — освободить участки мёртвых;
- compact или evacuate — переместить живые объекты и убрать фрагментацию;
- update references — исправить ссылки после перемещения.
Конкретный сборщик сочетает эти операции, часть выполняет конкурентно с приложением, часть — во время stop-the-world паузы.
Поколения
Большинство объектов живёт недолго, поэтому heap часто делят на young и old. Новые объекты обычно появляются в Eden/TLAB; пережившие сборки могут перемещаться или продвигаться в old. Межпоколенные ссылки отслеживаются специальными структурами, чтобы не сканировать весь heap при каждой young collection.
Термины Minor, Major и Full GC не стандартизованы одинаково для всех collectors. Нельзя выводить причину паузы только из названия: нужны GC logs и документация выбранного алгоритма.
Что влияет на приложение
- allocation rate и объём живого графа;
- размер heap;
- крупные объекты;
- количество ссылок между регионами;
- требования к latency и throughput;
- ошибочное удержание объектов — memory leak возможен и в Java.
System.gc() — просьба, а не гарантия. Финализаторы также не дают гарантии.
На собеседовании
Соберёт ли GC цикл объектов? Да, если цикл недостижим от roots.
Все ли фазы concurrent? Нет; даже concurrent collectors имеют короткие STW-фазы.
Что важнее количества созданных объектов? Скорость выделения, объём выживших данных и требования к паузам.
Почему Java-приложение может течь? Достижимая коллекция, listener, cache или ThreadLocal продолжает удерживать ненужные объекты.
Связано: Сборщики мусора в Java, Garbage collector, Виды ссылок в java, Стек и куча в Java.