Как работает garbage collector в Java и по какому принципу он удаляет объекты
Что проверяют
Понимаете ли вы принцип достижимости и поколенческую гипотезу, а не просто знаете слово «сборщик».
Как отвечать
Основной принцип это достижимость. Сборщик берёт корни (локальные переменные на стеках потоков, статические поля, JNI-ссылки) и обходит граф ссылок. Всё, до чего не дошли, считается мусором. Именно поэтому циклические ссылки в Java не проблема: два объекта, ссылающиеся друг на друга, но недостижимые от корней, будут собраны.
Второй принцип поколенческий: большинство объектов умирает молодыми. Поэтому куча делится на молодое поколение (Eden и два Survivor) и старое. Новые объекты попадают в Eden, пережившие несколько сборок переезжают в старое. Молодая сборка частая и дешёвая, полная редкая и дорогая.
Как это делается технически: живые объекты копируются в свободную область, а не удаляются по одному. Отсюда и уплотнение памяти, и то, что стоимость молодой сборки зависит от числа выживших, а не от объёма мусора.
Сборщики, которые стоит назвать: G1 по умолчанию с версии 9, делит кучу на регионы и старается уложиться в заданную паузу; ZGC и Shenandoah с паузами меньше миллисекунды на кучах в сотни гигабайт; Parallel для пропускной способности; Serial для маленьких приложений.
Важно добавить: System.gc() это просьба, а не команда, и в проде её не вызывают. Утечки в Java бывают и при сборщике: объект, оставшийся в статической коллекции или в слушателе, достижим и потому вечен.
Где спотыкаются
Говорят про подсчёт ссылок, которого в Java нет.
Считают, что finalize гарантированно вызовется, хотя он давно объявлен устаревшим.
Уверены, что утечка памяти в Java невозможна.
Не могут объяснить, зачем нужны два Survivor.