Ошибка в абстракции на самом деле не в том, что сборка мусора недетерминирована, а в том, что объекты «заинтересованы» в вещах, на которые они ссылаются, и не интересуются вещами, на которые они не держатся. Ссылки. Чтобы понять почему, рассмотрим сценарий объекта, который поддерживает счетчик того, как часто рисуется конкретный элемент управления. При создании он подписывается на событие рисования элемента управления, а при удалении отписывается. Событие click просто увеличивает поле, а метод getTotalClicks()
возвращает значение этого поля.
Когда объект счетчика создан, он должен заставить ссылку на себя быть сохраненной в элементе управления, который он отслеживает. Элемент управления действительно не заботится об объекте счетчика и был бы так же рад, если бы объект счетчика и ссылка на него перестали существовать, но пока ссылка существует, он будет каждый раз вызывать обработчик событий этого объекта он рисует сам. Это действие абсолютно бесполезно для контроля, но будет полезно любому, кто когда-либо будет вызывать getTotalClicks()
объект.
Если, например, метод должен был создать новый объект «счетчик краски», выполнить какое-либо действие с элементом управления, наблюдать, сколько раз элемент управления был перекрашен, а затем отказаться от объекта счетчика краски, объект останется подписанным на событие, даже хотя никому не было бы дела, если бы объект и все ссылки на него просто исчезли. Однако объекты не могут быть собраны, пока не получен сам элемент управления. Если бы метод был вызван много тысяч раз за время существования элемента управления (вероятный сценарий), он мог бы вызвать переполнение памяти, но тот факт, что стоимость N вызовов, вероятно, будет O (N ^ 2) или O (N ^ 3), если обработка подписки не была очень эффективной и большинство операций фактически не включало рисование.
Этот конкретный сценарий может быть реализован путем предоставления элементу управления слабой ссылки на контр-объект, а не сильной. Модель слабой подписки полезна, но не работает в общем случае. Предположим, что вместо того, чтобы хотеть иметь объект, который отслеживает один тип события из одного элемента управления, нужно иметь объект регистрации событий, который контролирует несколько элементов управления, а механизм обработки событий системы был таков, что каждому элементу управления нужна ссылка в другой объект журнала событий. В этом случае объект, связывающий элемент управления с регистратором событий, должен оставаться активным только до тех пор, пока обаконтролируемый элемент управления и регистратор событий остаются полезными. Если ни элемент управления, ни регистратор событий не содержат строгой ссылки на связывающее событие, оно прекратит свое существование, даже если оно все еще «полезно». Если один из них содержит сильное событие, время жизни связывающего объекта может быть бесполезно продлено, даже если другой умирает.
Если нигде во вселенной нет ссылки на объект, объект можно смело считать бесполезным и исключить из существования. Однако тот факт, что ссылка существует на объект, не означает, что этот объект «полезен». Во многих случаях фактическая полезность объектов будет зависеть от наличия ссылок на другие объекты, которые - с точки зрения GC - совершенно не связаны с ними.
Если объекты детерминированы уведомлением, когда никто не заинтересован в них, они смогут использовать эту информацию, чтобы гарантировать, что каждый, кто извлечет выгоду из этих знаний, будет проинформирован. Однако в отсутствие такого уведомления не существует общего способа определить, какие объекты считаются «полезными», если известно только существующее множество ссылок, а не семантическое значение, связанное с этими ссылками. Таким образом, любая модель, которая предполагает, что наличие или отсутствие ссылок достаточно для автоматизированного управления ресурсами, будет обречена, даже если GC сможет мгновенно обнаруживать отказ от объекта.