Какой простой способ объяснить, как работает сборщик мусора? - PullRequest
6 голосов
/ 08 марта 2009

У меня короткая концентрация внимания, поэтому я не смог пробраться через статью в Википедии .

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

Коллектор, очевидно, должен знать обо всех выделенных объектах и ​​корневых объектах. Как он определяет достижимость каждого из этих объектов?

Ответы [ 7 ]

2 голосов
/ 08 марта 2009

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

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

Java и .NET используют (среди прочего) сборку мусора поколений, где каждый объект изначально считается очень быстрым (гипотеза поколений). Затем он использует некоторые оптимизации, чтобы ускорить циклы сбора мусора и, таким образом, не нарушать работу программ. Раньше GC нередко блокировали программу во время ее работы, иногда на несколько секунд.

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

1 голос
/ 22 января 2013

Простой (но распространенный) подход к сбору мусора был бы аналогичен нахождению всего ценного в здании и его перемещению в новое здание, затем взрыву старого здания и замене его пустым. Чтобы свести к минимуму количество перемещаемых объектов, система может использовать несколько зданий разных размеров. Все новые объекты идут в небольшом здании. Когда он заполнен, все полезное копируется в среднее здание, а небольшое здание взорвано и заменено. Если в среднем здании осталось меньше, чем мелкое здание, все полезное будет перенесено в большое здание, а затем среднее здание будет взорвано и заменено. Если кажется, что в большом здании скопилось слишком много мусора, все полезное будет скопировано в другое большое здание, а затем большое здание будет взорвано и заменено. Несмотря на то, что небольшое здание будет взорвано и заменено, большая часть того, что находится в нем, будет ненужным и его не нужно будет копировать. Аналогичным образом, к тому времени, когда необходимо будет заменить среднее здание, большая часть его содержимого будет заброшена, поэтому лишь небольшое количество нужно будет перенести в большое здание. Копирование всего, что находится в большом здании, будет дорогостоящим, но эта операция не должна будет выполняться так часто.

1 голос
/ 28 августа 2010

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

1 голос
/ 08 марта 2009

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

Это приводит к вопросу о том, как сборщик мусора определяет, какие объекты могут быть удалены. Для этого есть различные методы, но две из них, о которых вы услышите много, - это «отметка и разметка» и «подсчет ссылок» (они часто встречаются в учебниках), и их стоит знать, чтобы понять основные идеи сборки мусора ,

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

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

0 голосов
/ 08 марта 2009

Вы можете думать о работающей программе (может быть, я должен быть специфичен для Java) как число Threads. Виртуальная машина может использовать корневой фрейм каждого потока как root. Затем он может пройтись по дереву достижимости всего, на что ссылается этот корень (плюс все кадры стека под корнем).

Все остальное недоступно

0 голосов
/ 08 марта 2009

Начните с корневых объектов (т. Е. Находящихся в стеке в вашем main () -эквиваленте), затем просто следуйте за каждым указателем / ссылкой и пометьте каждый объект как «достижимый». Продолжайте, пока не отметите каждый объект. Остальные объекты (которые не были помечены) являются мусором.

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

0 голосов
/ 08 марта 2009

Сборщик должен знать расположение ссылок на объекты в области глобальных переменных, а также в кадре активации каждого вызова функции / метода / процедуры для каждого потока. Регистры процессора также могут содержать ссылки на объекты. Некоторая информация должна предоставляться либо компилятором, либо виртуальной машиной.

...