Версия языка Java и платформы выполнения Java 17 с долгосрочной поддержкой (LTS) была запущена 14 сентября 2021 года. Давайте узнаем, что нового в Java 17 и следует ли вам обновляться.
Многие приложения используют более старые версии Java, включая более ранние LTS-версии Java: Java 11 и Java 8.
Почему Вам следует перейти на самую последнюю версию Java? Обновление до Java 17 хоть и требует усилий, но чтобы максимально использовать новые возможности внутри JVM, стоит обновится.
Возможности JAVA 17
Поддержка macOS и AArch64
Одной из важнейших функций JVM, добавленной в эту версию, является расширение поддержки macOS на архитектуре AArch64 с использованием JEP 391. Он будет поддерживать последнюю серию процессоров (M1), выпущенных Apple для своих компьютеров в прошлом году.
Это не обязательно имеет большое значение для пользователей на этих платформах, поскольку некоторые производители запустили версии JDK, которые поддерживают эту архитектуру и даже возвращают поддержку с Java 8. Однако официальная печать одобрения необходима для обеспечения будущего обслуживания и поддержки платформы. Для сравнения, поддержка платформы Linux / AArch64 была добавлена в Java 9, а Windows / AArch64 - в Java 16.
Закрытые классы
Закрытые классы - это функция, которая была введена в Java 17. Функция закрытых классов завершила свою пробную фазу и стала официальной платформой и языком Java 17. Это позволяет разработчику указывать допустимые подтипы, которые может иметь тип, и препятствовать другим расширять или реализовывать его способом, который не предназначен.
Закрытые классы также позволяют компилятору генерировать ошибки во время компиляции при попытке преобразовать незапечатанный тип в недопустимый подтип. Java 17 также предоставляет новый конвейер рендеринга для приложений AWT / Swing, которые запускаются на macOS с использованием Apple Metal API вместо OpenGL. Он имеет улучшенный API и расширенные функции для генерации случайных чисел.
Изменения, удаления и ограничения в Java 17
Java 17 также содержит несколько изменений, удалений и новых ограничений.
Инкапсуляция внутренних компонентов JDK
Одним из изменений является завершение процесса инкапсуляции внутренних компонентов JDK. Впервые это было введено в Java 9 и выдавало предупреждения во время выполнения, когда пользователь пытался использовать отражение или что-то подобное, чтобы обойти обычные ограничения на использование внутренних API. Для регулирования такого поведения также были добавлены аргументы командной строки.
Начиная с Java 9, были созданы различные API, предлагающие единый способ выполнения наиболее часто используемых задач; пользователи будут использовать эти API внутри компании. В Java 16 значение по умолчанию было изменено с предупреждения на отключение доступа к генерированию исключения. Однако для изменения поведения он использует аргумент командной строки.
В Java 17 аргумент командной строки устранен, и это ограничение можно деактивировать. Это означает, что весь несанкционированный доступ к этим внутренним API теперь защищен.
Всегда строгая семантика с плавающей запятой
Дополнительное “удаление” можно описать как повторное введение всегда строгой семантики с плавающей запятой. Java 1.2 внесла изменения в семантику с плавающей запятой, используемую в Java по умолчанию, что позволяет JVM использовать небольшую точность в вычислениях с плавающей запятой для повышения производительности. В классы и методы, где должна была использоваться строгая семантика, было добавлено strictfp ключевое слово. С тех пор в процессоры были введены различные типы наборов команд, что позволяет использовать строгую семантику с плавающей запятой без лишних затрат. Необходимость в реализации семантики по умолчанию или строгой семантики устранена.
Java 17 удаляет предыдущую семантику по умолчанию, и все операции с плавающей запятой выполняются строго. Термин strictfp все еще присутствует. Однако это не имеет никакого эффекта и вызывает предупреждение во время компиляции.
Компиляция с опережением времени (AOT)
Java 9 представила компиляцию с опережением времени (AOT) в качестве экспериментальной функции, использующей компилятор Graal, а JIT-код был написан с использованием Java. Java 10 сделала компилятор Graal пригодным для использования в качестве JIT-компилятора в OpenJDK, включив интерфейс JVMCI. С момента ее выпуска произошло значительное улучшение. Компилятор Graal претерпел огромные усовершенствования, и его JVM называется GraalVM.
Активация RMI
Активация RMI была отменена в JEP 407 после ее удаления из Java 8 и, наконец, устарела и помечена как требование для удаления в Java 15. Активация RMI предоставила метод для включения ресурсов распределенных объектов по требованию с использованием RMI. Тем не менее, она использовалась минимально, и в настоящее время доступна лучшая альтернатива. Удаление части активации не повлияет на оставшуюся часть RMI.
Удаление API апплета
В JEP 398 API апплетов наконец-то был назначен для удаления, первоначально удаленный в Java 9. API апплета предоставил способ интегрировать элементы управления Java AWT / Swing в веб-страницу в браузере. Однако ни один современный браузер не может поддерживать это, что означает, что апплеты были практически недоступны в течение последнего десятилетия или около того.
Менеджер безопасности
Наиболее критичным недостатком является диспетчер безопасности (JEP 411). Security Manager используется уже некоторое время, начиная с Java 1.0. Он был разработан, чтобы ограничить то, что Java может делать локально на компьютере, например, ограничить доступ к сетям, файлам и другим сетевым ресурсам. Он также пытается изолировать код, которому не доверяют, блокируя отражение и определенные API.
Завершение работы Security Manager началось в Java 12. Был добавлен аргумент командной строки для блокирования использования менеджера безопасности во время выполнения. Изменение, внесенное в Java 17, означает, что при попытке установить диспетчер безопасности либо из командной строки, либо динамически во время выполнения в JVM будет сгенерировано предупреждение во время выполнения.
Функции инкубатора и предварительного просмотра
Многие задавались вопросом, будет ли в Java 17 какие-либо функции предварительного просмотра и инкубатора, учитывая, что Java 17 продвигалась как версия с долгосрочной поддержкой. В Java 17 есть два модуля инкубатора и функция предварительного просмотра!
Векторный API
Векторный API (JEP 414) в настоящее время находится на втором этапе инкубатора. API позволяет разработчикам определять векторные вычисления, которые JIT-компилятор затем преобразует в соответствующую векторную инструкцию, поддерживаемую архитектурой процессора, на котором работает JVM (например, используя наборы инструкций SSE или AVX).
Раньше разработчикам приходилось использовать скалярные функции или создавать собственные библиотеки, специфичные для платформы. Реализация векторного API на Java также обеспечивает бесперебойный запасной механизм, который был сложным в более ранних версиях.
Стандартизация векторного API позволяет классам в JDK использовать его. Методы Java Arrays mismatch() могут быть изменены для запуска на Java вместо этого, устраняя необходимость поддерживать и писать несколько реализаций для конкретных платформ в JVM.
Внешняя функция и API памяти
Дополнительная функция инкубатора называется API внешних функций и памяти (JEP 412). Это эволюция и слияние двух других модулей инкубатора Java 16, то есть API внешнего компоновщика (JEP 389) и API внешней памяти (JEP 393). Оба они предоставляют доступ к встроенной памяти и коду с использованием статически типизированного программирования, написанного на Java.
Сопоставление шаблонов для Switch
Последняя функция предварительного просмотра языка, включенная в Java 17, - это включение сопоставления с шаблоном для Switch (JEP 406). Эта языковая функция расширяет выражения и инструкции switch в соответствии с типом, аналогично синтаксису, используемому с помощью сопоставления с образцом (JEP 394), который стал стандартным в Java 16.
В прошлом, если вы хотели выполнять различные действия, основанные на динамической природе объекта, вам требовалось бы построить цепочку if-else, используя экземпляр проверок, таких как:
String type(Object o) { if (o instanceof List) { return "A List of things."; } else if (o instanceof Map) { return "A Map! It has keys and values."; } else if (o instanceof String) { return "This is a string."; } else { return "This is something else."; } }
Комбинируя выражение switch, а также новую функцию сопоставления с шаблоном для коммутаторов, процесс может быть сведен к чему-то подобному:
String type(Object o) { return switch (o) { case List l -> "A List of things."; case Map m -> "A Map! It has keys and values."; case String s -> "This is a string."; default -> "This is something else."; }; }
Как вы, возможно, заметили, в процессе проверки происходит объявление переменной. Как и другие переменные в шаблоне, соответствие экземпляра указывает на то, что этот объект был проверен на тип и приведен и доступен из переменной в пределах ее текущей области.
Функция предварительного просмотра - это еще один шаг к сопоставлению с шаблоном. Следующим шагом будет включение возможности деконструкции массивов и записей.
Следует ли вам перейти на Java 17?
Да, вы должны постоянно обновляться до самой последней версии, однако не сразу после первого дня. Возможно, используемое вами программное обеспечение и библиотеки не были обновлены для обеспечения совместимости с Java 17, поэтому вам, возможно, придется подождать некоторое время, пока это будет сделано.
Если вы застряли на LTS-версии Java, такой как Java 8 или Java 11, в языке и в самой JVM есть множество опций, которые требуют обновления до Java 17. Поскольку это релиз для долгосрочного обслуживания, высока вероятность того, что ваша производственная среда в конечном итоге тоже будет обновлена до Java 17.
Если вы начинаете совершенно новый проект или находитесь в процессе подготовки вашего проекта для Java 17, переход на Java 17 скорее раньше, чем позже, вероятно, является наиболее эффективным выбором, поскольку это снижает затраты на перемещение. Это также позволяет разработчикам, работающим над проектом, использовать все новейшие функции и операционную сторону.
Вы можете воспользоваться многими улучшениями, которые произошли за последние несколько лет, такими как улучшенная поддержка контейнеров, работающих на Java, а также новые реализации сборщика мусора с низкой задержкой.