Перекрестные ссылки и сборка мусора - PullRequest
10 голосов
/ 07 ноября 2008

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

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

Ответы [ 3 ]

18 голосов
/ 07 ноября 2008

Как указано в этом SO вопросе , круговая ссылка хорошо управляется.

Java не выполняет подсчет ссылок, она использует отслеживание сборки мусора (например, разметка и очистка, копирование коллекции или некоторая их комбинация). Если следовать всем активным ссылкам, чтобы выяснить, какие объекты «достижимы», а затем все остальное убирает.

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

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

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

Подробнее о недоступном состоянии вы найдете в Правда о сборке мусора :

Недоступен

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

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

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

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

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

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

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

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

2 голосов
/ 07 ноября 2008

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

0 голосов
/ 07 ноября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...