Как ответить
Сборщик мусора (GC) автоматически освобождает память, занятую объектами, на которые больше нет ссылок из корневых точек (стек, статические поля, JNI). В Java и .NET используется поколенческая гипотеза: большинство объектов живут недолго, поэтому кучу делят на молодое и старое поколения. Это позволяет собирать молодое поколение часто и быстро, а старое — реже.
Рассмотрим на примере HotSpot JVM. Молодое поколение состоит из Eden и двух Survivor-областей (S0, S1). Новые объекты попадают в Eden. Когда он заполняется, происходит minor GC: живые объекты копируются в S0, а Eden очищается. При следующем minor GC объекты из Eden и S0 копируются в S1, счётчик возраста увеличивается. Объекты, пережившие несколько циклов (по умолчанию 15), перемещаются в Old Generation. Когда Old заполняется, запускается major GC — он может быть mark-sweep или mark-compact, в зависимости от выбранного алгоритма.
Основные алгоритмы сборки:
- Mark-Sweep — обходит граф объектов, помечает живые, затем удаляет мёртвые. Оставляет фрагментацию.
- Mark-Compact — после разметки сдвигает живые объекты в начало области, устраняя фрагментацию. Требует остановки приложения (stop-the-world).
- Copying — используется в молодом поколении: живые объекты копируются в другую область, старая очищается целиком. Быстро, но требует дополнительной памяти.
Типы GC в Java:
- Serial — однопоточный, подходит для маленьких приложений с кучей до ~100 МБ. Паузы могут быть длинными.
- Parallel — многопоточный, ориентирован на пропускную способность. Хорош для бэка, где важна скорость обработки, а не паузы.
- CMS (Concurrent Mark-Sweep) — старался минимизировать паузы, но страдал от фрагментации и «promotion failure». Устарел.
- G1 (Garbage First) — делит кучу на регионы (по 1–32 МБ), собирает регионы с наибольшим количеством мусора. Паузы предсказуемы, обычно < 10 мс. Стандартный с Java 9.
- ZGC — с Java 11 (экспериментальный), паузы < 1 мс независимо от размера кучи. Использует цветные указатели и concurrent перемещение.
Пример настройки JVM для G1 с целевой паузой 5 мс:
-XX:+UseG1GC -XX:MaxGCPauseMillis=5 -Xms2g -Xmx2gВсе GC останавливают приложение (stop-the-world) на время разметки корней и некоторых фаз. Современные сборщики (G1, ZGC) делают большую часть работы конкурентно, сокращая паузы до миллисекунд. Выбор GC зависит от требований: для высоконагруженных систем с большими кучами подходит G1 или ZGC, для пакетной обработки — Parallel.