Сборка мусора на Java - PullRequest
       43

Сборка мусора на Java

9 голосов
/ 31 мая 2010

На слайдах, которые я пересматриваю, написано следующее:

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

Подсчет ссылок стоит дорого - он требует действий при каждом изменении ссылки и не обнаруживает циклические структуры, но может постепенно восстанавливать пространство.

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

Я понимаю принципы того, почему подсчет ссылок стоит дорого, но не понимаю, что «не определяет циклические структуры, но может постепенно восстанавливать пространство». средства. Может ли кто-нибудь помочь мне немного, пожалуйста?

Спасибо

Ответы [ 5 ]

5 голосов
/ 31 мая 2010

Подсчет ссылок не определяет циклические структуры ...

Допустим, у вас есть два объекта O1 и O2. Они ссылаются друг на друга: O1 -> O2 и O2 -> O1, и никакие другие объекты не ссылаются на них. У них обоих будет счетчик ссылок 1 (один реферер).

Если ни O1, ни O2 недоступны из корня GC, их можно безопасно собрать мусором. Это не обнаруживается при подсчете ссылок, так как они оба имеют счетчик ссылок> 0.

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

... но он может постепенно восстанавливать пространство.

Инкрементная часть относится к тому факту, что вы можете быстро собирать некоторые объекты, на которые ссылаются 0, прерывать их и продолжать в другое время без проблем.

Если алгоритм трассировки будет прерван, то в следующий раз, когда это запланировано, его нужно будет начинать заново. (Дерево ссылок могло измениться с самого начала!)

1 голос
/ 31 мая 2010

"не обнаруживает циклические структуры"

Допустим, у меня есть объект A. A нужен другой объект с именем B, чтобы выполнить свою работу. Но B нужен другой объект с именем C, чтобы выполнить свою работу. Но C по той или иной причине нужен указатель на A. Таким образом, график зависимости выглядит так:

A -> B -> C -> A

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

Допустим, наша основная программа создала такую ​​структуру во время своего выполнения, и основная программа имела указатель на A, в результате чего счет A был равен двум. Что происходит, когда эта структура выходит за рамки? Счетчик ссылок A уменьшен до единицы.

Но обратите внимание! Теперь A, B и C имеют количество ссылок, равное единице, хотя они недоступны из основной программы . Так что это утечка памяти. В Википедии есть деталей о том, как решить эту проблему.

«он может постепенно восстанавливать пространство»

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

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

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

1 голос
/ 31 мая 2010
  1. Простой подсчет ссылок не может разрешить случаи, когда A относится к B, а B относится к A. В этом случае и A, и B будут иметь счетчик ссылок 1 и не будут собираться, даже если нет других ссылок.
  2. Подсчет ссылок может немедленно восстановить пространство, когда счетчик ссылок какого-либо объекта становится равным 0. Нет необходимости ждать цикла GC, сканировать другие объекты и т. Д. Таким образом, в некотором смысле он работает постепенно, так как он восстанавливает пространство от объектов по одному один.
0 голосов
/ 31 мая 2010

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

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

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

Вот что делает трассировка. Он определяет, какие части кучи являются островами и могут быть освобождены, а какие еще связаны с материком, то есть где-то статические переменные.

0 голосов
/ 31 мая 2010

Представьте, что у вас есть три объекта (A, B, C): A имеет ссылку на B, B имеет ссылку на C и C имеет ссылку на A. Но ни у одного другого объекта нет ссылки на один из них. Это независимая циклическая структура. Использование традиционного подсчета ссылок не позволит сборщику мусора удалить цикл, поскольку на каждый объект все еще ссылаются. Но до тех пор, пока ни у кого нет упоминания об одном из трех, их можно / нужно удалить. Я полагаю, постепенное восстановление пространства означает, как работает подсчет ссылок при поиске экземпляров без ссылок, без циклов и т. Д.

...