Является ли Java GC уничтожить объекты, если переменные экземпляра все еще имеют ссылку?

Я читал некоторые из руководств по сборке мусора Java в Интернете, но я все еще немного неясен и хотел убедиться, что у меня нет утечек памяти в моем коде.

Собирает ли Java GC объекты, потерявшие ссылку, но его переменные все еще имеют ссылку?

Итак, скажем, у меня есть SomeObject:

public class SomeObject {
    public ObjectVar var;

    public SomeObject() {
        var = new ObjectVar();
    }
}

И мой код:

SomeObject obj1 = new SomeObject();
SomeObject obj2 = new SomeObject();
obj2.var = obj1.var;
obj1 = null;

Таким образом, obj1 var имеет ссылку, но obj1 больше не имеет ссылки. Итак, GC уничтожит obj1, но сохранит var в живых? (Я так полагаю, просто хотел убедиться). Спасибо!

Ответ 1

Вот что будет (см. комментарии ниже)

// obj1 and obj1.var get created
SomeObject obj1 = new SomeObject();
// obj2 and obj2.var get created
SomeObject obj2 = new SomeObject();
// old obj2.var becomes eligible for GC
obj2.var = obj1.var;
// obj1 becomes eligible for GC
obj1 = null;

В конце концов остаются два объекта, которые не получают GCd - obj2 и предыдущий obj1.var, который теперь называется obj2.var.

Примечание. В частном случае класса ObjectVar, являющегося нестационарным внутренним классом SomeObject, сохранение ссылки на obj1.var также будет содержать obj1. Это связано с тем, что внутри класса SomeObject.ObjectVar имеется скрытая переменная типа SomeObject, которая ссылается на внешний объект внутреннего класса.

Ответ 2

Да, конечно.

Помните, что вы сохраняете в поле var, фактически ссылаетесь на объект, а не на сам объект. Поэтому, когда GC собирает obj1, объект var не тронут (не нужно касаться), тем более, что он имеет ссылку из obj2, которая все еще жива и нула.

Ответ 3

Да - поведение, как вы описываете. Общее правило сбора мусора заключается в том, что объекты становятся доступными только в том случае, если вы не можете связаться с ними по какой-либо жесткой ссылке. Любые объекты, которые вы можете достичь таким образом, никогда не будут собираться с мусором (за исключением мягких/слабых ссылок).

Ответ 4

Проще говоря, если объект по-прежнему доступен по пути ссылок, он, как гарантируется, выживет. Если такого пути нет, объект больше не может быть доступен и может быть безопасно собран.

После первых двух строк память выглядит так:

o1  --> SomeObj#1 --> ObjectVar#1
o2  --> SomeObj#2 --> ObjectVar#2

Все 4 объекта могут быть достигнуты, если в это время произойдет сбор мусора, ни один из них не будет собран.

После 3-й строки это выглядит так:

o1  --> SomeObj#1 --> ObjectVar#1
                      ^
o2  --> SomeObj#2 -----    ObjectVar#2

Теперь доступны только 3 объекта; сборщик мусора может удалить ObjectVar # 2.

После 4-й строки это выглядит так:

o1      SomeObj#1 --> ObjectVar#1
                      ^
o2  --> SomeObj#2 -----   ObjectVar#2

Доступны только два объекта; сборщик мусора может удалить SomeObj # 1 и ObjectVar # 2, но должен содержать SomeObj # 2 и ObjectVar # 1.