WikiSort.ru - Программирование

ПОИСК ПО САЙТУ | о проекте

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

Определение

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

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

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

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

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

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.

Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".

Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.

Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .




Текст в блоке "Читать" взят с сайта "Википедия" и доступен по лицензии Creative Commons Attribution-ShareAlike; в отдельных случаях могут действовать дополнительные условия.

Другой контент может иметь иную лицензию. Перед использованием материалов сайта WikiSort.ru внимательно изучите правила лицензирования конкретных элементов наполнения сайта.

2019-2024
WikiSort.ru - проект по пересортировке и дополнению контента Википедии