Как ответить
Сборщик мусора автоматически освобождает память, занятую объектами, на которые больше нет ссылок. Основная идея — найти мёртвые объекты и вернуть их память в кучу. В Java, C#, Go и других языках с управляемой памятью GC работает как фоновый процесс, который периодически запускается и анализирует граф ссылок.
Самый распространённый подход — работа от корней (roots). Корни — это статические поля, локальные переменные в стеке, регистры. GC обходит все достижимые объекты, начиная с корней. Всё, что не было посещено, считается мусором. Алгоритмы бывают разные: Mark-Sweep (пометить живые объекты, потом очистить мёртвые), Mark-Compact (после пометки ещё сдвинуть живые объекты, чтобы не было фрагментации) и Copying (разделить кучу на два полупространства, живые копировать в свободное полупространство).
Современные GC (например, в HotSpot JVM или .NET CLR) — поколенческие. Куча делится на поколения: молодое (Young Gen) и старое (Old Gen). Большинство объектов живут недолго, поэтому их выгодно собирать быстро и часто в молодом поколении с помощью Copying-алгоритма (Minor GC). Объекты, выжившие несколько сборок, перемещаются в старое поколение, где сборки происходят реже и выполняются Mark-Compact или Mark-Sweep (Major GC).
Есть ещё G1 GC (Garbage First) в Java — он делит кучу на регионы и приоритизирует сборку тех, где больше всего мусора. Также используется Shenandoah или ZGC — они снижают паузы за счёт concurrent-работы (например, с помощью цветных указателей или read barriers).
Из практики: если в Java приложении происходит длительная Stop-The-World пауза, это часто означает, что в Old Gen накопилось много объектов, требующих полного GC. Типичные настройки — размеры поколений, пороги выживаемости, количество параллельных потоков сборщика. Для low-latency систем лучше выбирать GC с минимальными паузами (ZGC) и внимательно следить за аллокациями и утечками (например, неявные ссылки через ThreadLocal или кэши).
В Python или JavaScript GC тоже есть, но там часто используется счётчик ссылок в комбинации с циклическим сборщиком (mark-sweep для циклов). В C# — аналогично Java, три поколения, Background GC. В Go — concurrent, Tri-color marking (белый, серый, чёрный), работает без Stop-The-World на весь цикл.
Главное понимать: GC — не панацея. Нужно писать код с учётом его работы — избегать лишних аллокаций в циклах, не держать ссылки на большие объекты дольше необходимого, использовать пулы объектов, если аллокаций много.