Написать пост

Как использовать новые возможности Java 17

Аватарка пользователя Siarhei Starykau

Рассказываем, как использовать обновления Java 17, чтобы повысить производительность и безопасность приложений.

Java 17 была выпущена почти 2 года назад, в сентябре 2021 года, но, возможно, именно к этой версии популярного языка программирования стоит присмотреться, если вы начинаете новый проект или желаете обновить версию Java, чтобы использовать улучшенные возможности.

Java 17 является версией с долгосрочной поддержкой (long-term support), а это значит, что она будет получать обновления, в том числе, связанные с безопасностью, в течение длительного времени. Проще говоря, это версия, которая будет использоваться в индустрии на протяжении, как минимум, нескольких лет – так, как сейчас используется предыдущая версия с долгосрочной поддержкой Java 11.

Если Вы хотите использовать новейшие версии фреймворков Spring 6 и Spring Boot 3, Вам также понадобится версия Java не ниже 17

Что было улучшено в Java 17

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

Производительность

Java 17 быстрее Java 11 на 6-16% в зависимости от используемого сборщика мусора:

  • На 8.66% быстрее для сборщика мусора по умолчанию (G1GC – default garbage collector)
  • На 6.54% быстрее для параллельного сборщика мусора (ParallelGC – Parallel Garbage Collector)

Java 17 также несколько быстрее, чем Java 16.

Безопасность

В плане безопасности изменения произведены в нескольких областях:

1. Были удалены части кода, которые уже были помечены как deprecated, или же были экспериментальными и не получили широкого применения:

  • Applet API
  • RMI Activation
  • 
Security Manager
  • Экспериментальные компиляторы AOT и JIT

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

3. Были добавлены новые особенности языка программирования:

  • Запечатанные (закрытые) классы – sealed classes
  • Контекстно-специфичные фильтры десериализации

Остановимся на новых возможностях языка Java 17 подробнее.

Запечатанные классы и интерфейсы

Запечатанный класс позволяет ограничивать или выбирать его подклассы. Класс не может расширять запечатанный класс, если его нет в списке разрешенных дочерних классов родительского класса. Основной мотив здесь – иметь возможность для суперкласса быть широко доступным, но не широко расширяемым.

Класс запечатывается с использованием ключевого слова sealed. За запечатанным классом должно следовать ключевое слово permits вместе со списком классов, которые могут его расширить. Аналогичным образом можно создавать и запечатанные интерфейсы. Вот простой пример запечатанного класса:

public abstract sealed class Device permits Laptop, Smartphone {...}

Класс, который его расширяет, должен иметь один из модификаторов:

  • final – класс не может быть больше расширен
  • sealed – нам нужно указать классы, которые могут его расширять, посредством модификатора permits
  • non-sealed – класс снова становится доступным для стандартного расширения

Пример:

public non-sealed class Laptop extends Device {...}

Контекстно-специфичные фильтры десериализации

Сериализация — это механизм преобразования состояния объекта в памяти в поток байтов и сохранение объекта в файл. Простой пример сериализации:

Laptop laptop = new Laptop();String filename = "laptop.ser";FileOutputStream file = new FileOutputStream(filename);ObjectOutputStream out = new ObjectOutputStream(file);out.writeObject(laptop);out.close();file.close();

Десериализация — это обратный процесс, при котором поток байтов используется для воссоздания фактического объекта Java в памяти. Пример:

String filename = "laptop.ser";FileInputStream file = new FileInputStream(filename);ObjectInputStream in = new ObjectInputStream(file);Laptop laptop = (Laptop)in.readObject();in.close();file.close();

Объект Java является сериализуемым, если его класс или любой из его суперклассов реализует либо интерфейс java.io.Serializable, либо субинтерфейс java.io.Externalizable.

Десериализация ненадежных данных может привести к уязвимостям, позволяющим злоумышленнику выполнить произвольный код.

Laptop laptop = (Laptop)in.readObject();

Метод readObject в java.io.ObjectInputStream создаст сериализуемый объект класса Laptop. Если созданный объект имеет какие-либо уязвимые данные, например, удаленное выполнение кода, то это может вызвать проблему безопасности в системе.

Чтобы решить эту проблему, были представлены фильтры десериализации – ещё в Java 9. Они позволяют проверять поток данных, прежде чем его десериализировать. Это можно сделать статически или динамически через ObjectInputFilter API.

FileInputStream file = new FileInputStream(filename);ObjectInputStream in = new ObjectInputStream(file);ObjectInputFilter filesOnlyFilter = ObjectInputFilter.Config.createFilter("!com.example.Laptop;");in.setObjectInputFilter(filesOnlyFilter);Laptop laptop = (Laptop)in.readObject();

Java 17 добавляет больше гибкости фильтрам десериализации, теперь появилась возможность использовать FilterFactory. Следующий код использует слияние существующего и нового фильтров:

ObjectInputFilter.Config.setSerialFilterFactory((filter1, filter2) -> ObjectInputFilter.merge(filter2,filter1));

Также появилась возможность создавать фильтры в удобочитаемом коде посредством методов allowFilter() and rejectFilter() в ObjectInputFilter.

Итог

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

Об авторе

Сергей Стариков (Siarhei Starykau), Solution Architect в компании EPAM Systems, работаю с языком программирования Java 18 лет.

Следите за новыми постами
Следите за новыми постами по любимым темам
4К открытий5К показов