Що нового в Java 17?

Нововведення Java 17: аналіз оновлення та основні зміни

14 вересня 2021 року відбувся офіційний реліз Java 17, версії з довгостроковою підтримкою (LTS). Давайте розглянемо ключові нововведення Java 17 та обговоримо, чи варто здійснювати оновлення.

Значна кількість програмних продуктів все ще використовує попередні версії Java, зокрема Java 11 і Java 8, які також є версіями LTS.

Чому ж компаніям слід розглянути перехід на новітню версію Java? Оновлення до Java 17 – це інвестиція, що відкриває доступ до нових можливостей і вдосконалень віртуальної машини Java (JVM).

Широке використання Docker і образів Docker полегшує перехід на Java 17 з мінімальними зусиллями. Розробники можуть налаштувати конвеєри безперервної інтеграції/розгортання (CI/CD) і запускати все в контейнерах Docker. Це дозволяє іншим командам продовжувати роботу зі старими версіями Java, використовуючи відповідні образи Docker, не створюючи конфліктів.

Ключові особливості Java 17

Розширена підтримка macOS і AArch64

Важливим доповненням до JVM у цій версії є покращена підтримка macOS на архітектурі AArch64 (JEP 391). Це включає підтримку процесорів M1, які Apple почала використовувати у своїх комп’ютерах у минулому році.

Хоча це не є критичною проблемою для користувачів цих платформ, оскільки вже існують JDK, що підтримують цю архітектуру, офіційне визнання від Oracle є важливим для забезпечення надійної підтримки в майбутньому. Для порівняння, підтримка Linux/AArch64 була додана у Java 9, а Windows/AArch64 у Java 16.

Запечатані класи

Запечатані класи (Sealed Classes) – це функціональність, яка перейшла з пробної версії до офіційного статусу в Java 17. Вона дозволяє розробникам контролювати, які підтипи може мати певний тип, запобігаючи несанкціонованому розширенню або впровадженню.

Запечатані класи дозволяють компілятору виявляти помилки під час спроби перетворити не дозволений підтип. Також, Java 17 надає новий механізм візуалізації для програм AWT/Swing на macOS, використовуючи Apple Metal API замість OpenGL. Введено покращений API та вдосконалені методи генерації випадкових чисел.

Зміни, видалення та обмеження у Java 17

Java 17 впроваджує ряд змін, видалень і нових обмежень.

Інкапсуляція внутрішніх компонентів JDK

Однією з ключових змін є завершення процесу інкапсуляції внутрішніх API JDK. Цей процес був розпочатий у Java 9, де користувачі отримували попередження під час спроби доступу до внутрішніх API через рефлексію. Для керування цією поведінкою були додані аргументи командного рядка.

Починаючи з Java 9, з’явилися нові API, які пропонують стандартизовані методи виконання загальних завдань. У Java 16 поведінка за замовчуванням була змінена з попередження на виняток при спробі доступу, але все ще можна було використовувати аргумент командного рядка для зміни цієї поведінки.

У Java 17 аргумент командного рядка видалено, а обмеження не можна вимкнути. Це означає, що несанкціонований доступ до внутрішніх API тепер повністю заблокований.

Завжди строга семантика чисел з плаваючою комою

Іншим важливим моментом є повернення до семантики Always-Strict Floating Point. У Java 1.2 були введені зміни в семантику з плаваючою комою, які дозволяли JVM жертвувати невеликою точністю обчислень для підвищення продуктивності. Ключове слово `strictfp` використовувалося для вказівки, що має застосовуватися сувора семантика. З розвитком процесорів, сувора семантика більше не створює значних накладних витрат.

Java 17 скасовує стару семантику за замовчуванням, тепер всі операції з плаваючою комою виконуються строго. Ключове слово `strictfp` залишається, але не має впливу і викликає попередження під час компіляції.

Попередня компіляція (AOT)

У Java 9 була запроваджена попередня компіляція (AOT) як експериментальна функція, використовуючи компілятор Graal. Java 10 зробила компілятор Graal доступним як JIT-компілятор в OpenJDK, включаючи інтерфейс JVMCI. З того часу компілятор Graal значно покращився, і тепер існує окрема JVM GraalVM.

Виключення RMI Activation

Активація RMI ( JEP 407) була видалена після того, як була визнана застарілою в Java 8 і, остаточно, позначена для видалення в Java 15. Активація RMI використовувалася для динамічного створення об’єктів через RMI. Однак, через низьку популярність, було прийнято рішення про її видалення. Решта функціональності RMI не постраждала.

Видалення API аплетів

API аплетів був остаточно видалений ( JEP 398), вперше оголошений застарілим у Java 9. API аплетів використовувався для інтеграції елементів керування Java AWT/Swing у веб-сторінки. Але, оскільки сучасні браузери не підтримують цю технологію, аплети практично не використовуються вже протягом десятиліття.

Менеджер безпеки

Менеджер безпеки ( JEP 411) є ще однією застарілою функцією. Він використовувався починаючи з Java 1.0 для обмеження дій, які Java може виконувати локально, наприклад, доступ до мережі, файлів та інших ресурсів. Менеджер безпеки намагався ізолювати ненадійний код, блокуючи рефлексію та деякі API.

Процес відмови від менеджера безпеки почався в Java 12. Був доданий аргумент командного рядка для блокування його використання під час виконання. Зміни в Java 17 означають, що спроба встановлення менеджера безпеки з командного рядка або динамічно під час виконання викличе попередження під час виконання.

Інкубатор та функції попереднього перегляду

Чи будуть у Java 17 функції попереднього перегляду та інкубатора, враховуючи її статус версії LTS? Так, Java 17 включає два модулі інкубатора та одну функцію попереднього перегляду.

Vector API

Vector API ( JEP 414) знаходиться на другій стадії інкубатора. Цей API дозволяє розробникам визначати векторні обчислення, які JIT-компілятор перетворює у векторні інструкції, підтримувані архітектурою процесора (наприклад, SSE або AVX).

Раніше, для виконання подібних операцій, розробникам доводилося використовувати скалярні функції або створювати платформно-залежні бібліотеки. Vector API у Java забезпечує плавний резервний механізм.

Стандартизація Vector API дає можливість використовувати його в класах JDK. Метод Java Arrays mismatch() тепер може виконуватися у Java, що усуває необхідність у підтримці та написанні кількох платформно-залежних реалізацій у JVM.

API зовнішніх функцій та пам’яті

Ще однією функцією інкубатора є API зовнішніх функцій та пам’яті ( JEP 412). Це результат злиття двох модулів інкубатора Java 16: Foreign Linker API ( JEP 389) та API зовнішньої пам’яті ( JEP 393). Ці API забезпечують доступ до нативної пам’яті та коду через статично типізоване програмування на Java.

Зіставлення шаблонів для `switch`

Останньою функцією попереднього перегляду, включеною у Java 17, є зіставлення шаблонів для виразу `switch` ( JEP 406). Ця функція розширює можливості `switch` до відповідності типу, подібно до синтаксису зіставлення шаблонів ( JEP 394) з Java 16.

Раніше, для виконання різних дій на основі динамічного типу об’єкта, необхідно було використовувати ланцюг `if-else` з перевірками `instanceof`, наприклад:

 String type(Object o) {
  if (o instanceof List) {
    return "Список.";
  }
  else if (o instanceof Map) {
    return "Карта.";
  }
  else if (o instanceof String) {
    return "Рядок.";
  }
  else {
    return "Щось інше.";
  }
}
 

Завдяки зіставленню шаблонів у `switch`, цей процес можна спростити до:

 String type(Object o) {
  return switch (o) {
    case List l -> "Список.";
    case Map m -> "Карта.";
    case String s -> "Рядок.";
    default -> "Щось інше.";
  };
}
 

В процесі перевірки, як бачите, є оголошення змінної. Збіг екземпляру вказує на те, що об’єкт був перевірений на тип і приведений, і доступний через змінну у межах поточної області.

Функція попереднього перегляду є ще одним кроком до повноцінного зіставлення шаблонів. Наступним кроком є можливість деконструкції масивів та записів.

Чи варто оновлюватися до Java 17?

Так, оновлення до останньої версії Java є рекомендованим, хоча не обов’язково в перший день її випуску. Важливо переконатися, що ваші програмні залежності та бібліотеки сумісні з Java 17, що може зайняти деякий час.

Якщо ви використовуєте старіші LTS-версії Java, такі як Java 8 або Java 11, Java 17 пропонує значні покращення в мові та JVM. Оскільки це версія з довгостроковою підтримкою, є висока ймовірність того, що ваші виробничі середовища також перейдуть на Java 17.

Якщо ви починаєте новий проект або готуєте свій проект до Java 17, перехід на цю версію є ефективним рішенням, яке заощадить витрати на міграцію. Також, це дасть розробникам доступ до всіх новітніх функцій та можливостей.

З Java 17 ви можете скористатися багатьма вдосконаленнями, які були представлені за останні роки, зокрема покращеною підтримкою контейнерів, що працюють на Java, і новими збирачами сміття з низькою затримкою.