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

Сбор мусора включает прохождение списка выделенных объектов (либо всех объектов или объектов в конкретном поколении), либо определение доступных достижений.

  • Как поддерживается этот список? Выполняют ли время выполнения для языков GC гигантский список всех объектов?

  • Кроме того, из того, что я понимаю, GC включает в себя хостинг стека вызовов для поиска ссылок на объекты - как алгоритм различает GC-способные указатели и примитивные данные?

Ответ 1

  • Система управления памятью отслеживает размер каждого выделенного объекта, как и на C или С++. Один из способов, который обычно делается, заключается в том, чтобы система управления памятью выделяла дополнительный size_t перед каждым распределением, который отслеживает размер каждого объекта. Менеджер памяти также должен отслеживать размер каждого свободного блока, чтобы он мог повторно использовать блоки для их размещения.

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

    В фазе развертки сборщик мусора перемещает кучу снизу вверх, переходя от распределения к распределению на основе этих size_t s и освобождает все, что не отмечено.

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


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

Ответ 2

Сбор мусора включает прохождение списка выделенных объектов (либо всех объектов или объектов в конкретном поколении), либо определение доступных достижений.

Не совсем. ГЦ подразделяются на трассировку и подсчет ссылок (см. Единая теория сбора мусора). Трассировка GC начинается с набора глобальных корней и отслеживает все доступные для них объекты. Счетные подсчеты GC подсчитывают количество ссылок на каждый объект и возвращают его, когда счетчик достигает нуля. Ни один из них не требует списка, включая недостижимые объекты.

Как поддерживается этот список? В течение времени выполнения для языков GC хранится гигантский список всех объектов?

Педагогические решения, такие как HLVM, могут содержать список всех объектов, потому что это просто, но это редко.

Кроме того, из того, что я понимаю, GC включает в себя хостинг стека вызовов для поиска ссылок на объекты - как алгоритм различает GC-способные указатели и примитивные данные?

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

Обратите внимание, что вам также нужно найти локальные ссылки, хранящиеся в регистрах, а также в стеке.