Перекрестные ссылки и сбор мусора

Существует приложение с обширным графиком объектов. Этот граф в основном состоит из набора подграфов, которые связаны с остальной частью графика через единственную ссылку. Но внутренне каждый такой подграф имеет некоторое количество перекрестных ссылок между объектами. Время от времени подобный подграф должен быть выброшен. Достаточно ли просто установить нулевое единственное рефери, которое указывает на этот подграф, чтобы сделать его пригодным для сбора мусора?

Моя забота заключается в том, что внутренние перекрестные ссылки могут "защищать" весь подграф от сбора мусора. Другими словами, сборщик мусора достаточно мудр, чтобы понять, что все ссылки в подграфе не оставляют границ подграфа, и поэтому весь подграф может быть очищен.

Ответ 1

Как указано в этом вопросе fooobar.com/questions/115428/..., круговая ссылка хорошо управляется.

Java не выполняет подсчет ссылок, он "маркирует и продувает" сбор мусора. Если следует все активные ссылки, чтобы узнать, какие объекты "достижимы", а затем очищает все остальное.

Ссылки на объекты, которые не достигают цели, не влияют на достижимость, поэтому не имеет значения, являются ли они нулевыми или нет.

О единственном случае, когда установка ссылки на значение NULL, возможно, имеет значительный эффект, заключается в отбрасывании очень большого объекта в середине длинного метода.

В этом случае установка нулевой ссылки на график поможет создать остров изоляции (даже для внутренних циклических ссылок), как описано в этом статья.

Вы найдете более подробную информацию о недостижимом состоянии в "Правда об сборке мусора" :

Недоступен

Объект переходит в недостижимое состояние, когда нет более сильных ссылок на него.
Когда объект недоступен, он является кандидатом на сбор.

Обратите внимание на формулировку:
Просто потому, что объект является кандидатом на сбор, не означает, что он будет немедленно собраны. JVM может откладывать сбор до тех пор, пока не возникнет необходимость в том, чтобы их память потреблялась объектом.

Важно отметить, что не всякая сильная ссылка будет содержать объект в памяти. Они должны быть ссылками на цепочку из корня сборщика мусора. Корни GC - это специальный класс переменной, который включает в себя:

  • Временные переменные в стеке (любого потока)
  • Статические переменные (из любого класса)
  • Специальные ссылки из собственного кода JNI

Циркулярные сильные ссылки не обязательно вызывают утечку памяти. Рассмотрим код, создающий два объекта, и присваивает им ссылки друг на друга.

public void buidDog() {
   Dog newDog = new Dog();
   Tail newTail = new Tail();
   newDog.tail = newTail;
   newTail.dog = newDog;
}

Перед возвратом метода есть сильные ссылки из временных переменных стека в методе buildDog, указывающие как на Собака, так и на хвост.

После того, как метод buildDog вернется, Dog и Tail становятся недоступными из корня и являются кандидатами на сбор (хотя виртуальная машина не может фактически собирать эти объекты на неопределенное количество времени).

Ответ 2

Да - сборщик мусора может справиться с круговыми ссылками и т.д.

Ответ 3

JVM работает над понятием "острова недостижимости". Если есть недостижимый "остров" взаимосвязанных объектов, то этот набор объектов имеет право на сбор мусора в целом.