Сколько объектов будет иметь право на сбор мусора после выполнения "m1 = null; m2 = null;"?

Я смущен, чтобы понять после выполнения m1 = null; m2 = null;. Сколько объектов будет иметь право на сбор мусора?

public class MyTest {
    MyTest m;

    void show() {
        System.out.println("Hello this is show method.");
    }

    public static void main(String args[]) {
        MyTest m1 = new MyTest();
        MyTest m2 = new MyTest();
        MyTest m3 = new MyTest();
        m1.m = m2;
        m2.m = m3;
        m3.m = m1;
        m1 = null;
        m2 = null;
        // Question here: How many objects will be eligible for garbage collection?
    }
}

Ответ 1

Ноль.

Диаграмма ссылок объекта выглядит следующим образом:

Циркуляр

Вы можете видеть, что ссылка является круговой. Ссылка от main до m3 сохраняет объект m3 живым. В свою очередь, m3 сохраняет m1, что сохраняет m2 от GC.

Обратите внимание, что если вы установите m3 на null, все три объекта будут иметь право на GC одновременно, несмотря на круглые ссылки, существующие для каждого из них. GC достаточно умен, чтобы понять, что все ссылки поступают от объектов, имеющих право на GC, и собирают все три.

Ответ 2

Потенциально все 3 из них. Никакие переменные не упоминаются после маркера //, поэтому оптимизатор находится в пределах своих прав, чтобы удалить их с кадра в этот момент.

Ответ 3

Voila! GC ничего не собирается здесь! Давайте посмотрим, что на самом деле происходит здесь. Когда вы создали три объекта m1, m2 и m3 в MyTest, объект был создан, как показано ниже (например, идентификатор объекта начинается с 410):

m1    MyTest  (id=410)
    m    null
m2    MyTest  (id=412)
    m    null
m3    MyTest  (id=414)
    m    null

Когда вы инициализируете

m1.m = m2;
m2.m = m3;
m3.m = m1;

Теперь объекты выглядят следующим образом:

m1    MyTest  (id=410)
    m    MyTest  (id=412)
m2    MyTest  (id=412)
    m    MyTest  (id=414)
m3    MyTest  (id=414)
    m    MyTest  (id=410)
        m    MyTest  (id=412)
            m    MyTest  (id=414)
                m    MyTest  (id=410)
                    .
                    .
                    . (This is circular)

Но после повторной инициализации m1 и m2 до null объекты выглядят следующим образом:

m1    null
m2    null
m3    MyTest  (id=414)
    m    MyTest  (id=410)
        m    MyTest  (id=412)
            m    MyTest  (id=414)
                m    MyTest  (id=410)
                .
                .
                .

Посмотрите, m1 и m2 теперь null, но их ссылки все еще живы в m3!

Ответ 4

Нет, поскольку они все еще доступны по круговой ссылке, которую вы строите там через m3