Garbage collector
Сборщик мусора автоматически переиспользует память объектов, которые больше недостижимы из работающей программы. Недостижимость важнее количества ссылок: цикл из двух объектов также собирается, если до него нельзя дойти от GC roots.
GC roots
К типичным корням относятся:
- локальные ссылки активных стековых frames;
- статические поля загруженных классов;
- активные Java-потоки;
- ссылки из JNI и внутренних структур JVM.
Трассировка начинает с корней и помечает достижимый граф. Всё, что не помечено, считается кандидатом на освобождение.
Основные операции
| Операция | Назначение |
|---|---|
| Mark | найти достижимые объекты |
| Sweep | освободить непомеченные области |
| Compact | сдвинуть живые объекты и убрать фрагментацию |
| Copy | перенести живые объекты в другую область |
Разные collectors сочетают эти операции и по-разному распределяют работу между потоками приложения и GC. Stop-the-world означает, что Java-потоки приостановлены на определённой фазе; это не означает, что весь цикл сборки обязательно выполняется в одной длинной паузе.
Поколения
Большинство объектов живёт недолго. Generational collectors используют это: новые объекты сначала попадают в молодое поколение, пережившие сборки могут перемещаться или учитываться как старые. Конкретные названия областей и алгоритмы зависят от collector; не у каждого GC схема одинакова.
В Java 17 доступны, среди прочих, Serial, Parallel, G1, ZGC и Shenandoah (наличие может зависеть от сборки JDK). G1 является обычным выбором по умолчанию в HotSpot Java 17, но collector выбирают по требованиям к throughput, паузам и памяти, а не по одному названию.
Ссылочные типы
SoftReference, WeakReference и PhantomReference дают разные гарантии
достижимости. Они не заменяют явную политику кэша. finalize устарел и
ненадёжен; для ресурсов применяют try-with-resources и при необходимости
Cleaner.
try (var stream = Files.lines(path)) {
return stream.count();
} // файл закрывается детерминированно, независимо от GCДиагностика
Высокая частота сборок — симптом, а не диагноз. Проверяют allocation rate,
размер живого набора, паузы, heap dump и удерживающие ссылки. Вызов
System.gc() — только просьба JVM и не гарантирует немедленную сборку.
Области памяти: Стек и куча в Java.
Вопросы для собеседования
- Соберёт ли GC циклические ссылки? Да, если цикл недостижим от roots.
- Что такое stop-the-world? Период остановки потоков приложения для фазы GC.
- Почему GC не закрывает файл вовремя? Достижимость и внешние ресурсы —
разные задачи; нужен
close. - Что такое memory leak в Java? Ненужные объекты остаются достижимыми.
- Гарантирует ли
System.gc()сборку? Нет. - Зачем compaction? Уменьшить фрагментацию и получить непрерывное свободное место.