Как сборщик мусора Java обрабатывает саморекламу?

Надеюсь, простой вопрос. Возьмем, например, круговой список:

class ListContainer
{
  private listContainer next;
  <..>

  public void setNext(listContainer next)
  {
    this.next = next;
  }
}

class List
{
  private listContainer entry;
  <..>
}

Теперь, поскольку это циклически связанный список, когда один элемент добавлен, он имеет ссылку на себя в следующей переменной. При удалении единственного элемента в списке запись имеет значение null. Нужно ли устанавливать ListContainer.next как null для сборщика мусора, чтобы освободить его память или автоматически обрабатывать такие саморегуляции?

Ответ 1

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

Подходы подсчета без ссылки применяют более всеобъемлющий тест на доступность, чтобы определить, может ли объект быть собранным. Эти системы определяют объект (или набор объектов), который всегда считается достижимым. Любой объект, для которого ссылки доступны из этого графа объектов, считается неприемлемым для сбора. Любой объект, не доступный напрямую из этого объекта, не является. Таким образом, циклы не влияют на доступность и могут быть собраны.

См. также страницу Wikipedia трассировку сборщиков мусора.

Ответ 2

Циркулярные ссылки являются (разрешимой) проблемой, если вы полагаетесь на подсчет ссылок, чтобы решить, мертв ли ​​объект. Никакая реализация Java не использует подсчет ссылок, AFAIK. Более новые Sun JREs используют сочетание нескольких типов GC, все помечают и меняют или копируют, я думаю.

Вы можете больше узнать о сборке мусора вообще Wikipedia, а некоторые статьи о java GC здесь и здесь, например.

Ответ 3

Фактический ответ на это зависит от реализации. Sun JVM отслеживает некоторый набор корневых объектов (потоков и т.п.), И когда ему нужно делать сборку мусора, отслеживается, какие объекты доступны из них и сохраняет их, отбрасывая остальное. Это на самом деле сложнее, чем для некоторых оптимизаций, но это основной принцип. Эта версия не заботится о круговых ссылках: пока ни один живой объект не держит ссылку на мертвую, он может быть GCed.

Другие JVM могут использовать метод, известный как подсчет ссылок. Когда для объекта создается ссылка, некоторый счетчик увеличивается, а когда эта ссылка выходит за пределы области действия, счетчик уменьшается. Если счетчик достигает нуля, объект завершается и сбор мусора. Однако эта версия позволяет использовать круглые ссылки, которые никогда не собирались собирать мусор. В качестве защиты многие такие JVM включают в себя метод резервного копирования для определения того, какие объекты на самом деле мертвы, которые он периодически запускает, чтобы разрешать самореференции и дефрагментировать кучу.

Ответ 4

В качестве ответа, отличного от ответа (существующие ответы более чем достаточны), вы можете проверить технический документ о системе сбора мусора JVM, если вас вообще интересует GC. (Любая, только Google JVM Garbage Collection)

Я был поражен некоторыми из используемых методов, и, читая некоторые из концепций, таких как "Иден", я действительно впервые понял, что Java и JVM на самом деле могут быстро побить C/С++. (Всякий раз, когда C/С++ освобождает объект/блок памяти, задействован код... Когда Java освобождает объект, он фактически ничего не делает, поскольку в хорошем коде OO большинство объектов создаются и освобождаются почти сразу, это удивительно эффективно.)

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

Примечание. Я просто понял, что это вводит в заблуждение. Распределение С++ STACK происходит очень быстро - моя задача состояла в том, чтобы выделить объекты, которые могут существовать после завершения текущей процедуры (что, я считаю, ДОЛЖНЫ быть всеми объектами - это то, о чем вам не нужно думать, если вы собираетесь думать в OO, но на С++ скорость может сделать это непрактичным).

Если вы выделяете классы С++ в стеке, это распределение будет как минимум быстрее, чем Java.

Ответ 5

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

Ответ 6

yes Java Сборщик мусора сборщика самореференции!

How?

Существуют специальные объекты, называемые корнями для сбора мусора (корни GC). Они всегда достижимы, и каждый объект имеет свой собственный корень.

Простое приложение Java имеет следующие корни GC:

  • Локальные переменные в основном методе
  • Основной поток
  • Статические переменные основного класса

enter image description here

Чтобы определить, какие объекты больше не используются, JVM периодически запускает то, что очень точно называют алгоритмом mark-and-sweep. Он работает следующим образом:

  • Алгоритм проходит все ссылки на объекты, начиная с GC корней и отмечает каждый объект, найденный как живой.
  • Вся память кучи, которая не занята отмеченными объектами, утилизирован. Он просто обозначен как свободный, по сути, неиспользуемые объекты.

Поэтому, если какой-либо объект недоступен из корней GC (даже если он является саморегументированным или циклическим), он будет подвергнут сбору мусора.

Ответ 7

Просто, да.:)

Отъезд http://www.ibm.com/developerworks/java/library/j-jtp10283/

Все JDK (от Sun) имеют понятие "способность к достижению". Если GC не может "достичь" объекта, он уходит.

Это не какая-то "новая" информация (ваша первая для респондентов замечательная), но ссылка полезна, а краткость - это что-то сладкое.:)