В Java9 финализаторы устарели, вместо них были введены очистители. Какая разница между двумя?

В Java9 финализаторы устарели, и была введена новая концепция очистителей. Какова была конкретная причина этого? Есть ли какой-либо конкретный сценарий или причина, по которой очистители следует предпочесть финализатору (учитывая, что ни один из них не рекомендуется)?


person Chota Bheem    schedule 31.01.2018    source источник


Ответы (2)


Устаревание Finalizer в реестрах указывает причину решения: -

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

Кроме того, время финализации непредсказуемо, и нет гарантии, что будет вызван финализатор. Классы, экземпляры которых содержат ресурсы, не относящиеся к куче, должны предоставлять метод для явного освобождения этих ресурсов, а также должны реализовывать java.lang.AutoCloseable, если это уместно.

решением, предложенным в качестве альтернативы использованию финализаторов, были представленные очистители, которые обеспечивали простая регистрация и отмена функций очистки для объектов.

Cleaner и PhantomReference обеспечивают более гибкие и эффективные способы освобождения ресурсов при объект становится недоступным.

Приложения создают службу очистки для собственного использования, и служба закрывается, когда она больше не используется.

Использование: когда объект становится фантомным reachable действия по очистке, выполняемые на одном и том же, регистрируются и управляются очистителем. Регистрация ссылки на объект и соответствующее действие очистки возвращает Cleanable. Наиболее эффективное использование — явный вызов метода clean, когда объект закрыт или больше не нужен.

Примечание. До Java9 аналогичная реализация Cleaner была также находится в пакете sun.misc.

person Naman    schedule 31.01.2018

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

Чистильщики — это попытка создать процедуру, подобную финализатору, которая менее подвержена атакам финализатора. Но Чистильщики очень сложно написать правильно.

Что такое атака Finalizer?
Finalizer запускается, даже если объект не полностью сконструирован (например, если он выдает исключение внутри конструктора). Злоумышленник может создать подкласс вашего уязвимого класса и переопределить его finalize метод, возможно, в обход безопасности или проверок инвариантов. делается внутри конструктора.

Так зачем использовать очиститель.

  1. Не загрязняет общедоступный API класса (поскольку очистители и связанные с ними объекты являются частными)
  2. Не нужно создавать пустой метод final finalize, даже если он вам не нужен, чтобы предотвратить его переопределение подклассами в ходе атаки.
  3. Предотвращает атаки Finalizer.
  4. Очиститель запускается только один раз

РЕДАКТИРОВАТЬ: после рассмотрения я понял, что очистители не предотвращают атаку финализатора. Поэтому, даже если вы используете очиститель в нефинальном классе, создайте пустой метод final finalize.

person dkatzel    schedule 31.01.2018
comment
Спутал с пунктом 4. Означает ли это, что финализаторы могут запускаться более одного раза? - person Chota Bheem; 31.01.2018
comment
Я точно не собираюсь загрязнять свой код пустыми finalize() методами. Ваш сценарий имеет значение только в том случае, если 1) ваш код вообще имеет отношение к безопасности, 2) вы разрешаете ненадежному коду создавать подклассы вашего класса и 3) ваш конструктор переносит объект в эксплуатируемое состояние перед проверкой аргументов. Если вы проверяете аргументы перед выделением ресурсов, все finalize() методы злоумышленника увидят null ссылки. Если вы отклоните недопустимые аргументы перед вызовом конструктора суперкласса, завершения вообще не будет. - person Holger; 31.01.2018