Вычистит ли сборщик мусора объекты, если они ссылаются друг на друга, но не имеют ссылок из корня
Что проверяют
Понимаете ли вы, как сборщик вообще определяет мусор: по достижимости от корней, а не по счётчику ссылок. Следом почти всегда спрашивают про утечки в Android: если GC такой умный, откуда берутся утёкшие Activity.
Как отвечать
Да, вычистит. ART, как и JVM, использует трассирующий сборщик: он начинает с корней (GC roots) и помечает всё, до чего можно дойти по ссылкам. Что не помечено, то мусор, и неважно, сколько ссылок на объект идёт изнутри недостижимой группы.
Корнями считаются:
- локальные переменные и параметры в стеках живых потоков;
- статические поля загруженных классов;
- глобальные ссылки JNI из нативного кода;
- работающие потоки и объекты, на которых удерживается монитор.
Объекты A и B, ссылающиеся друг на друга, от корней недостижимы, значит, их соберут. Специальный поиск циклов трассирующему сборщику не нужен: цикл просто не попадает в граф достижимых объектов.
Циклы опасны при подсчёте ссылок. Так работает ARC в Swift и Objective-C: там цикл держит объекты вечно, пока одну из ссылок не сделают weak. Хорошо, если вы покажете, что видите эту разницу.
Дальше переходите к утечкам. В Android объект течёт, когда до него есть путь от корня, которого вы не заметили: Activity лежит в статическом поле или синглтоне, анонимный класс в Handler.postDelayed держит ссылку на внешний объект, слушатель не отписан в onDestroy, корутина в GlobalScope захватила View. Такие пути показывают LeakCanary и Memory Profiler в Android Studio.
Где спотыкаются
Отвечают «нет, ведь ссылки на объекты есть». Это логика подсчёта ссылок, к Java и Kotlin на Android она не относится.
Считают, что поля нужно обнулять вручную, чтобы помочь GC. Для недостижимых объектов это бессмысленно, обнулять стоит только ссылки, которые долгоживущий объект держит на короткоживущий.
Путают среды: называют G1 или CMS применительно к Android. На устройстве работает ART со своим сборщиком, в современных версиях это concurrent copying, а G1 и ZGC относятся к серверной HotSpot JVM.