Взаимные ссылки между объектами и поведение сборщика мусора в Java

Оба объекта становятся недостижимыми от GC roots и могут быть собраны, несмотря на взаимные ссылки. Java GC не опирается только на подсчёт ссылок.

Короткий ответ

Что ответить на собеседовании

Оба объекта становятся недостижимыми от GC roots и могут быть собраны, несмотря на взаимные ссылки. Java GC не опирается только на подсчёт ссылок.

Подробный разбор

Ответ с пояснениями

Условие

Рассмотрите, как будет вести себя система при наличии взаимных ссылок между объектами. Что произойдёт с объектами, если после их взаимного связывания ссылки из локальных переменных будут обнулены и будет запрошен запуск сборки мусора?

class A {
    B b;
}

class B {
    A a;
}

public class main {
    public static void main(String [] args){
        A objA = new A();
        B objB = new B();

        objA.b = objB;
        objB.a = objA;

        objA = null;
        objB = null;

        System.gc();
    }
}

Ответ

Оба объекта становятся недостижимыми от GC roots и могут быть собраны, несмотря на взаимные ссылки. Java GC не опирается только на подсчёт ссылок.

Цикл A ↔ B не удерживает объекты, если к нему больше нет пути от живых потоков, статических корней и других GC roots. Обнуление objA и objB устраняет показанные внешние ссылки. System.gc() лишь запрашивает сборку и не гарантирует немедленного освобождения памяти или конкретного момента исполнения. Иная ситуация была бы, если один из объектов сохранился в статической коллекции: тогда весь цикл оставался бы достижимым.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее