Почему JVM не уничтожает ресурс, как только его счетчик ссылок достигает 0? - PullRequest
8 голосов
/ 09 января 2012

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

if(obj.refCount == 0)
{
   delete  obj;
}

Есть ли какие-то большие преимущества в том, как Java делает то, что я пропустил?

Спасибо

Ответы [ 5 ]

18 голосов
/ 09 января 2012

Каждая JVM отличается, но JVM HotSpot не полагается в первую очередь на подсчет ссылок в качестве средства для сбора мусора. Преимущество подсчета ссылок заключается в простоте реализации, но оно по своей природе подвержено ошибкам. В частности, если у вас есть цикл ссылок (набор объектов, которые все ссылаются друг на друга в цикле), то при подсчете ссылок не будут корректно возвращаться эти объекты, поскольку все они имеют ненулевой счетчик ссылок. Это заставляет вас время от времени использовать вспомогательный сборщик мусора, который, как правило, работает медленнее (именно в Mozilla Firefox возникла именно эта проблема, и их решение заключалось в добавлении сборщика мусора за счет большей читаемости кода). Вот почему, например, такие языки, как C ++, обычно имеют комбинацию shared_ptr с, которые используют подсчет ссылок, и weak_ptr с, которые не используют циклы ссылок.

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

В HotSpot JVM используются различные методы сбора мусора, но его основной сборщик мусора называется сборщиком остановок и копий. Этот сборщик работает, размещая объекты в памяти рядом друг с другом, и позволяет чрезвычайно быстро (одна или две инструкции по сборке) размещать новые объекты. Когда пространство заканчивается, все новые объекты GC'ed одновременно, что обычно убивает большинство новых объектов, которые были построены. В результате сборщик мусора намного быстрее, чем обычная реализация с подсчетом ссылок, и в итоге получает лучшую локальность и лучшую производительность.

Для сравнения методов сбора мусора вместе с кратким обзором работы GC в HotSpot, вы можете проверить эти слайды лекций из курса компиляторов что я учил прошлым летом. Возможно, вы также захотите взглянуть на технический сборщик мусора HotSpot , в котором более подробно рассказывается о том, как работает сборщик мусора, включая способы настройки сборщика в приложении. база приложения.

Надеюсь, это поможет!

3 голосов
/ 09 января 2012

Подсчет ссылок имеет следующие ограничения:

  • Это ОЧЕНЬ плохо для производительности многопоточности (в основном, каждое назначение ссылки на объект должно быть защищено).
  • Вы не можете автоматически освобождать циклы
2 голосов
/ 09 января 2012

Поскольку он не работает строго на основе подсчета ссылок.

Рассмотрим циклические ссылки, которые более недоступны из «корня» приложения.

Например:

APP имеет ссылку на SOME_SCREEN

SOME_SCREEN имеет ссылку на SOME_CHILD

SOME_CHILDтеперь имеет ссылку на SOME_SCREEN

, APP удаляет ссылку на SOME_SCREEN.

В этом случае SOME_SCREEN по-прежнему имеет ссылку на SOME_CHILD, а SOME_CHILD по-прежнему имеет ссылку на SOME_SCREEN - поэтому в этом случае ваш пример не работает.

Теперь другие (Apple с ARC, Microsoft с COM, многие другие) имеют решения для этого и работают более похоже на то, как вы их описываете.

С ARC вы должны аннотировать ваши ссылки с ключевыми словами, такими как strong и weak, чтобы ARC знал, как обращаться с этими ссылками (и избегать циклических ссылок) ... (не читайте слишком далеков мой конкретный пример с ARC, потому что ARC обрабатывает эти вещи заранее во время процесса компиляции и не требует конкретной среды выполнения как таковой), так что это определенно можно сделать аналогично тому, как вы это описываете, но это просто не работаетс некоторыми функциями Java.Я также считаю, что COM работает более схоже с тем, как вы описываете ... но опять же, это не требует некоторого внимания со стороны разработчика.

На самом деле, ни одна "простая" схема подсчета ссылок никогда не будет работатьбез каких-либо усилий со стороны разработчика приложения (чтобы избежать циклических ссылок и т. д.)

0 голосов
/ 09 января 2012

потому что сборщик мусора в java основан на copying collector для объектов 'youg generation', и mark and sweep для объектов "поколений владения".

Ресурсы из: http://java.sun.com/docs/hotspot/gc1.4.2/faq.html

0 голосов
/ 09 января 2012

Поскольку сборщик мусора в современных JVM больше не отслеживает количество ссылок.Этот алгоритм используется для обучения работе GC, но он был ресурсоемким и подвержен ошибкам (например, циклические зависимости).

...