Рубрики
Без рубрики

Вступающий в силу Java Вторник! Избегайте финализаторов и очистителей!

Погружение в восьмую главу “Эффективная Java”. Помеченный как java, эффективный, дизайн, архитектура.

Вот мы и подошли к восьмой главе книги “Эффективная Java”, и это еще одна более узкая тема. Сегодня мы говорим о финализаторах и очистителях. А? Что это такое? Автор Effective Java просто как бы переходит к тому, почему их не использовать, и на самом деле не объясняет, для чего они существуют (возможно, потому, что он не хочет побуждать вас их использовать). В любом случае, я подумал, что было бы неплохо начать с того, что они собой представляют, прежде чем мы углубимся в то, почему мы не должны их использовать, потому что, когда я впервые прочитал о них, я никогда не слышал о них и не использовал их.

Эти две концепции в основном делают одно и то же, но двумя разными способами. Финализаторы являются старшим из двух вариантов и являются основной частью языка Java. Это метод в классе Объект , который может быть переопределен. Так что же он делает? Просто финализатор – это метод, который вызывается непосредственно перед удалением объекта сборщиком мусора. Эта функция может быть использована для многих целей, включая возвращение объекта к жизни (почему? 🤷 ), но чаще всего используется для очистки ресурсов объекта. Очистители – это более или менее однотипные вещи (но не часть класса Объект ) но для мира после Java 9, где финализаторы устарели и помогают преодолеть некоторые недостатки. Однако их все равно следует избегать.

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

Время, когда Финализатор Не определен Поскольку у нас нет контроля над тем, когда запускается сборщик мусора, мы также не можем быть уверены, когда запустится финализатор. Из-за этого мы не должны рассчитывать на то, что он очистит для нас конечные ресурсы, такие как дескрипторы файлов, поскольку он может не успеть сделать это вовремя. Хотя мы, скорее всего, получим некоторую согласованность поведения, если будем тестировать на той же JVM, на которой мы развертываем, но все равно будет много вариативности. Если мы развертываем на разных JVM, это становится еще более открытым для различных моделей поведения. Мы также рискуем тем, что поток финализатора будет выполняться с более низким приоритетом, чем остальные потоки в системе, и, следовательно, не сможет идти в ногу с созданием объектов.

Финализатор Никогда Не Может Быть Вызван Итак, что хуже, чем невозможность определить, когда будет запущен финализатор, так это осознание того, что финализатор может никогда не запуститься. Правильно, согласно спецификации, финализатор никогда не может быть вызван. Это должно сделать очевидным, что они не должны использоваться для очистки постоянного состояния. Существуют методы, которые могут увеличить ваши шансы на вызов финализатора ( System.gc и System.runFinalization ) но это все еще не гарантирует, что будет вызван финализатор.

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

Финализаторы Имеют Серьезные Затраты На производительность Поскольку финализаторы и очистители мешают эффективным алгоритмам сбора мусора, это может значительно замедлить работу. В эксперименте автора он увидел 50-кратное снижение производительности при использовании финализатора. Все любят хорошую производительность, так что это не то, чего мы хотим.

Хорошо, итак, мы рассмотрели все ужасные вещи, связанные с ними. Когда это еще может быть полезно. Во-первых, поскольку они устарели, в современных приложениях Java действительно нет необходимости в финализаторах. Итак, остаются чистящие средства, когда мы должны их использовать? Эффективная Java открывает два потенциальных варианта использования. Один из них заключался в том, чтобы действовать как защитная сетка для регулярной уборки. Хотя это не должно быть основным способом очистки элементов, оно может служить средством защиты, когда разработчики забывают вручную управлять своими ресурсами. Второй вариант использования – использовать его, когда у нас есть собственные компоненты, которыми управляет наш Java-код. Конечно, сборщик мусора не может управлять этими собственными компонентами, и поэтому нам приходится больше управлять им самим.

Наконец, мы рассмотрели, чего не следует делать, что мы должны делать вместо этого? Необходимость очистки ресурсов – это реальная проблема, которую все еще необходимо учитывать. Решение довольно простое. Просто попросите ваш класс реализовать AutoCloseable и реализовать метод close для очистки ресурсов, которые мы, возможно, создали в процессе эксплуатации объекта. Это отдает управление в наши руки. Мы подробнее поговорим об этом на следующей неделе в нашем следующем эпизоде.

Итак, вот оно что у нас есть. Завершители и очистители. Вы когда-нибудь ими пользовались? Тебе повезло хоть немного? Поделитесь в комментариях.

Оригинал: “https://dev.to/kylec32/effective-java-tuesday-avoid-finalizers-and-cleaners-18jh”