Подтвердить что ты не робот

Как реализованы слабые ссылки?

Интересно, как слабые ссылки работают внутри, например, в .NET или на Java. Мои две общие идеи:

  • "Intrusive" - добавить список слабых ссылок на самый верхний класс (класс объекта). Затем, когда объект уничтожен, все слабые ссылки могут быть итерированы и установлены в нуль.
  • "Неинтрузивный" - поддерживать хэш-таблицу указателей объектов на списки слабых ссылок. Когда слабая ссылка A создается для объекта B, в хэш-таблице будет изменена или создана запись, ключ которой будет указателем на B.
  • "Грязный" - для хранения специального хэш-значения с каждым объектом, который будет обнулен при уничтожении объекта. Слабые ссылки скопировали бы это хэш-значение и сравнили бы его с значением объекта, чтобы проверить, жив ли объект. Это, тем не менее, приведет к ошибкам нарушения прав доступа при непосредственном использовании, поэтому, я думаю, для этого должен быть дополнительный объект с этим значением хэша.

Любое из этих решений кажется чистым и эффективным. Кто-нибудь знает, как это делается?

4b9b3361

Ответ 1

Не уверен, что я понял ваш вопрос, но вы можете взглянуть на реализацию для класса WeakReference и его суперкласса Reference в Java. Он хорошо прокомментирован, и вы можете видеть, что у него есть поле, специально обработанное GC, а другое - непосредственно с помощью виртуальной машины.

Ответ 2

В .NET, когда создается WeakReference, GC запрашивает маркер/непрозрачный токен, представляющий ссылку. Затем, когда это необходимо, WeakReference использует этот дескриптор для запроса GC, если этот дескриптор все еще действителен (т.е. Исходный объект все еще существует), и если это так, он может получить фактическую ссылку на объект.

Итак, это создает список токенов/дескрипторов по адресам объектов (и, по-видимому, поддерживает этот список во время дефрагментации и т.д.)

Я не уверен, что я на 100% понимаю три пули, поэтому я не решаюсь угадать, какой (если есть) самый близкий к.

Ответ 3

Python PEP 205 имеет достойное объяснение того, как слабые ссылки должны вести себя на Python, и это дает некоторое представление о том, как они могут быть реализованы, Поскольку слабая ссылка неизменна, вы можете иметь только один для каждого объекта, к которому вы, при необходимости, передаете ссылки. Таким образом, когда объект уничтожается, только одна слабая ссылка должна быть аннулирована.

Ответ 4

Кажется, что реализация слабых ссылок хорошо хранится в секрете;-). Например, на данный момент в статье wikipedia нет каких-либо деталей реализации. Посмотрите на приведенные выше ответы (включая принятые): "Идите посмотреть на источник" или "Я думаю" , - \.

Из всех ответов только один, ссылающийся на Python PEP 205, проницателен. Как говорится, для любого отдельного объекта может быть не более одной слабой ссылки, если мы рассматриваем weakref как сущность.

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

Конечно, weakref указывает на исходный объект. Таким образом, вам просто нужно пройти через все доступные места, где обрабатываются ссылки на объекты, и добавить прозрачную обработку слабых ссылок (т.е. Автоматически разыгрывать их). ( "Прозрачная" альтернатива заключается в добавлении виртуального метода "доступа", который будет идентичным для большинства объектов и фактического разыменования для weakref.)

И поскольку объект имеет указатель на его weakref, тогда объект может NULLify weakref в собственном деструкторе.

Эта реализация довольно чиста (без магических "вызовов в GC" и т.д.) и имеет O (1) стоимость исполнения. Конечно, это довольно жадный от памяти - нужно добавить +1 поле указателя к каждому объекту, хотя обычно для 90 +% объектов, которые будут NULL. Конечно, у VHLL уже есть большие накладные расходы на каждый объект, и может быть шанс скомбинировать различные "дополнительные" поля. Например, тип объекта, как правило, представляет собой небольшую перечисление, поэтому может быть возможно объединить тип и некоторый вид ссылки weakref в одно машинное слово (скажем, сохранить слабые объекты на отдельной арене и использовать для этого индекс).

Ответ 5

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

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