Финализатор

Финализатор

Финализа́тор в объектно-ориентированных языках программирования, использующих механизм сборки мусора, — специальный метод, вызываемый средой исполнения перед удалением объекта сборщиком мусора.

Содержание

Определение

Финализатор — это метод класса, который автоматически вызывается средой исполнения в промежутке времени между моментом, когда объект этого класса опознаётся сборщиком мусора как неиспользуемый, и моментом удаления объекта (освобождения занимаемой им памяти). Финализатор для конкретного объекта всегда выполняется после того, как программа прекращает использовать данный объект и до того, как занимаемая объектом память будет освобождена сборщиком мусора. Удобно считать, что финализатор вызывается непосредственно перед удалением объекта из памяти, хотя это обычно не гарантируется.

Отличие от деструкторов

Внешне финализатор схож с деструктором класса, однако в действительности эффект действия и область применения этих методов существенно различаются. Различие вызвано тем, что момент вызова финализатора, в отличие от деструктора, не определён жёстко: финализатор всегда вызывается перед уничтожением объекта сборщиком мусора, но момент уничтожения зависит от режима работы сборщика мусора, объёма доступной оперативной памяти и активности использования памяти программой. Так, если свободной памяти мало и создание новых объектов происходит постоянно, потребность в сборке мусора возникает часто и финализатор, соответственно, с высокой вероятностью будет вызван вскоре после прекращения использования объекта. Если же памяти много, а потребление её программой мало, то от прекращения использования объекта до сборки мусора (и вызова финализатора) может пройти длительное время. Более того, если памяти много и новые объекты почти или совсем не создаются, то сборщик мусора может вообще не вызываться, а по завершении программы вся выделенная ей память будет просто возвращена операционной системе; в этом случае финализатор, возможно, вообще не будет вызван.

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

Финализаторы непредсказуемы, зачастую опасны и, чаще всего, не нужны.

— Joshua Bloch. Effective Java. Addison-Westley, 2001.

Вследствие сказанного, применение финализаторов весьма ограниченно. Для освобождения ресурсов в языках со сборкой мусора используется шаблон проектирования «dispose». Язык программирования C# поддерживает шаблон «dispose» неявно через интерфейс IDisposable и ключевое слово using, в Java 7 введён аналогичный механизм «try-with-resources».

Оправданное применение

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

Другой удачный способ применения финализатора — проверка очистки объекта перед удалением. Если объект при создании или по ходу своей работы захватывает ценные системные ресурсы, кроме памяти (открывает файлы или коммуникационные каналы, подключается к устройствам ввода-вывода), то, очевидно, в момент удаления объекта сборщиком мусора все эти ресурсы должны быть уже освобождены (то есть объект должен быть очищен). Ошибки очистки (когда объект в некоторых ситуациях не очищается или, что ещё хуже, очищается не полностью) очень коварны, их сложно выявлять, так как проявляются они при выполнении совсем не той части кода, где допущена ошибка. Как уже говорилось, проводить очистку в финализаторе неразумно, так как неизвестно, когда он будет вызван и вызовется ли вообще. Зато в финализаторе вполне уместно и удобно провести проверку того, полностью ли очищен объект, и выдать, в той или иной форме, сообщение об ошибке, если какой-то ресурс остался захваченным. Неважно, что финализатор может быть вызван поздно и не каждый раз; всё равно, если ошибка очистки объекта имеется, то рано или поздно финализатор «поймает» её.

Примеры

Создаваться финализаторы могут по-разному. В некоторых языках финализатор является частью стандартной библиотеки. Обычно в таких случаях он является виртуальным методом стандартного корневого класса, потомками которого являются все остальные классы в системе (в Java это метод finalize() класса Object). Могут финализаторы объявляться и с помощью специального синтаксиса. В C# синтаксис объявления финализатора позаимствован от деструкторов C++ — финализатором для класса Class становится метод с сигнатурой ~Class(). В языке Nemerle, построенном на основе C#, от этого синтаксиса отказались, поскольку сочли его провоцирующим ошибки.

Литература

  • Брюс Эккель. Философия Java. Библиотека программиста. 4-е изд. - СПб: Питер, 2009. ISBN 978-5-388-00003-3
  • Joshua Bloch. Effective Java. Addison-Westley, 2001.

Wikimedia Foundation. 2010.

Игры ⚽ Поможем написать курсовую

Полезное


Смотреть что такое "Финализатор" в других словарях:

  • Финализация — Финализатор в объектно ориентированных языках программирования, использующих механизм сборки мусора, специальный метод, вызываемый средой исполнения перед удалением объекта сборщиком мусора. Определение Финализатор это метод класса, который… …   Википедия

  • Паскаль (язык программирования) — Эта статья или раздел нуждается в переработке. В Паскале нет модулей, ООП и прочих новомодных веяний. Описание расширений должно присутствовать только в статьях о соответ …   Википедия

  • Терминатор — Терминатор: В науке и технике Терминатор (астрономия) (от лат. terminare  ограничивать)  линия светораздела, отделяющая освещённую (светлую) часть небесного тела от неосвещённой (тёмной) части. Терминатор (ДНК) … …   Википедия

  • Nemerle — Семантика: мультипарадигменный, объектно ориентированный, функциональный, императивный Тип исполнения: компилируемый Появился в: 0.9.3 16 мая …   Википедия

  • Деструктор (программирование) — Деструктор специальный метод класса, служащий для деинициализации объекта (например освобождения памяти). Содержание 1 Деструктор в Delphi 2 Деструктор в С++ …   Википедия

  • Деструктор — У этого термина существуют и другие значения, см. Деструкторы (экология). Деструктор  специальный метод класса, служащий для деинициализации объекта (например освобождения памяти). Содержание 1 Деструктор в Delphi 2 Деструктор в С++ …   Википедия

  • Деструктор класса — Деструктор специальный метод класса, служащий для деинициализации объекта (например освобождения памяти). Содержание 1 Деструктор в Delphi 2 Деструктор в С++ 3 Виртуальный деструктор …   Википедия

  • Паскаль (язык) — Pascal Семантика: процедурный Тип исполнения: компилятор Появился в: 1970 г. Автор(ы): Никлаус Вирт Паскаль (англ. Pascal) высокоуровневый язык программирования общего назначения. Один из наиболее известных языков программирования, широко… …   Википедия


Поделиться ссылкой на выделенное

Прямая ссылка:
Нажмите правой клавишей мыши и выберите «Копировать ссылку»