Является ли 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.