Привіт! Мене звати Микита Земницький, я Java Developer в NIX та спікер IT-конференції NIX MultiConf. У цій статті я розкажу про основні нововведення Java 17 на рівнях JDK та JVM, про зміни у мові, безпеці, платформах, а також порівняю популярні збирачі сміття для цієї версії Java. Окремо розберу недоліки нової Java, які, на мій погляд, можуть ускладнити роботу розробника.
Java 17 з’явилась наприкінці минулого року, але залишається майже непомітною на ринку — і це доволі прикро. Згідно опитування компанії NewRelic, на початку 2022 року більшість розробників користувалися 11-ою та 8-ою версіями Java: близько 48,5% та 46,5% відповідно. Доля ж 17-ої склала лише… 0,37%! Думаю, IT-фахівцям варто більше дізнатися про нову «довготривалу» Java, про її переваги і труднощі, з якими можна стикнутися в процесі роботи і врешті спробувати її на реальному проєкті.
Чим так особлива 17-та версія Java? Відповідь проста: це так званий реліз Long-Term Support, який автори будуть підтримувати до 2029 року.
Попереднім LTS була Java 11, яку представили ще 2018 року. Звісно, 11-ою версією і надалі можна користуватися і не хвилюватися про безпеку аж до вересня 2026 року. Всі знайдені вразливості до цього терміну будуть гарантовано виправлені. Але все ж таки прогрес не стоїть на місці, тому варто спробувати й нову версію.
На відміну від проміжних версій, LTS використовують у більшості проєктів. Кожні шість місяців випускається нова версія Java (non-LTS): від Java 12 до Java 16 включно, також вийшла аналогічна Java 18.
Єдина різниця з LTS полягає в тому, що її підтримка закінчується із появою наступної версії. Наприклад, підтримка Java 12 завершується разом із дебютом Java 13. І якщо хочете зберегти підтримку, вам потрібно перейти на Java 13. А це може викликати проблеми, якщо деякі з ваших залежностей ще не готові до нової версії.
Саме через це такою важливою і є прем’єра 17-ї версії. Що ж у ній цікавого?
Основні зміни в JDK
Передусім хочу виділити найголовніші зміни, що сталися з JDK:
- По-перше, з деяких методів було видалено
Finalize
. З ним була проблема: після «смерті» об’єкту він ставиться в чергу, щобFinalize
виконав свою роботу. Однак за специфікацією не гарантується його виконання — навіть до закінчення роботи JVM. Тому відFinalize
в самих JDK потихеньку позбавляються. - По-друге, незначні зміни у Java 17 пов’язані з інтерфейсами
Packer
таUnpacker
, реалізація класуPack200
. Раніше він більше використовувався для внутрішніх потреб, у зв’язку з чим кількість розчарованих через видалення користувачів, напевно, буде не такою й великою. Конструктор класуURLDecoder
у новій версій взагалі зник. - По-третє, при вивченні ряду класів
AWT
іSwing
помітно, що чимало класів змінили видимість. Як правило, вони були публічні, в них все було доступно звідусіль. Наразі багато класів сховали. Хоча ключові інтерфейси все одно залишаються видимими. - І врешті-решт також позначено для видалення
API Applet
. Тобто користуватися ним досі можна, але все ж таки це вже не рекомендується.
Ключові нововведення у JVM
УJava Virtual Machine найбільше змін відбулося із Gаrbage-колекторами — збирачами сміття. CMS тут видалили, так що вам так чи інакше доведеться обирати якийсь інструмент цього типу.
По дефолту ми маємо у системі G1. Ще існує ZGC, але він з’явився як експериментальний у Java 11. Проте там його краще не використовувати через певні невиправлені недоліки (це вже тема для окремої статті).
Важливим нововведенням є те, що у G1 з’явилися Abortable Mixed Collection. Під час збору сміття частина регіонів збирається безумовно. Завдяки цьому вони мають бути зібрані у цей цикл повністю. Інша ж частина, припустимо, 20% регіонів можуть бути зібрані в наступний цикл, якщо поточний не вкладається у часові обмеження.
Також G1 навчили аллокувати пам’ять та бути NUMA-Aware. Іншими словами, для багатонодних архітектур виділиться місце під нові об’єкти у пам’яті, що знаходиться ближче до Thread у виконавцю.
Інші незначні зміни у JVM націлені на те, щоб якомога більше процесів тривали паралельно з виконанням Java-програми.
Основна мета — зменшення пауз, аби вони не напружували користувачів, які не хочуть бачити затримки через Garbage Collector.
Треба сказати декілька слів і про Just-in-Time-компілятор. GraalVM тепер перебуває в окремому проєкті. Головна зміна Java Flight Recorder — це можливість стрімити події, які JFR записує, що дозволяє відстежувати зміни в режимі реального часу.
Новинки Java 17
Гадаю, чимало читачів вже знають їх, але хоча б коротко пробіжусь по цій темі. Так, стосовно мови були додані Sealed-класи, Switch-вирази, розширені екземпляри (Enhanced instanceof), текстові блоки та рекорди (Records).
Також у Java 17 додали Vector API, але тільки в інкубатор — тобто цей модуль можна підключити спеціальною командою. Крім цього, були додані Foreign Function та Memory API.
А ще Security Manager тепер відмічений як Deprecate.
Не можна забувати й про зміни щодо платформи MacOS: у ній був доданий рендеринг із використанням Metal API. Також маємо корисні Null Pointer Exception, які, напевно, багато хто чекав. Вони покажуть обширну інформацію про помилку — і не лише рядок, в якому сталася помилка, а й конкретний об’єкт, який виявився Null.
Відзначну декілька змін стосовно безпеки. Наприклад, були удосконалені сучасна криптографія та контекстно-залежні фільтри десеріалізації, а також розширене псевдовипадкове число (воно стало ще більш псевдовипадковішим).
G1 проти ParallelGC
Окремо хочу поговорити про збирачі сміття, ті самі Garbage Collectors, які я пригадав вище. Я вирішив порівняти два розповсюджені інструменти цього типу для Java 17: G1 та ParallelGC.
Garbage-First collector (G1) — це алгоритм складання сміття, представлений у віртуальній машині Oracle HotSpot Java (JVM) 6 та підтримуваний, починаючи з 7 Update 4.
Збирач сміття G1 — це довгострокова заміна CMS, призначена для багатопроцесорних машин із великим обсягом пам’яті. G1 намагається з високою ймовірністю досягти мети за часом припинення складання сміття, показуючи при цьому високу пропускну здатність із невеликою потребою в налаштуваннях.
ParallelGC іноді називають збирачем пропускної спроможності. Коли працює збирач сміття, він зупиняє всі потоки програми та виконує своє завдання, використовуючи кілька потоків. Таким чином, робота GC може виконуватися дуже ефективно без перерв. Зазвичай це найкращий спосіб мінімізувати загальний час, який витрачається на роботу збирача сміття у порівнянні з роботою програми. Однак окремі паузи Java-програми, викликані GC, можуть бути досить тривалими.
Порівняння цих інструментів було б неповним без статистики. Для цього поглянемо на звіт OptaPlanner, в якому порівнюється швидкість цих збирачів та показано, наскільки Java 17 краща для них.
Підкреслю, що цифри усереднені, але все одно дуже показові. За цими даними, 17-та Java швидша для G1 на 8,66%, аніж 11-та. Також вона швидша в порівнянні з минулою версією і для ParallelGC — на 6,54%. При цьому сам ParallelGC на 16,39% швидший, ніж G1.
З усього цього можна зробити висновок: Java 17 десь у середньому на 7% ефективніша для збирачів сміття — і це дуже круто.
Недоліки Java 17
Як не прикро про це говорити, але у новій LTS Java є не лише позитивні моменти. По-перше, у ній відсутні 100% зворотної сумісності. Ми звикли, що зворотна сумісність — це головна концепція, навколо якої вибудовуються нові версії Java. Але у 17-й було видалено досить велику кількість методів, які до цього позначалися як deprecated. Розробники мали багато часу для того, щоб видалити їх. Але для тих, хто цього так і не зробив, маю погані новини: ваш проєкт може просто не скомпілюватися.
Також багато внутрішніх модулів змінили видимість і стали приватними. Тому тепер у вас немає до них доступу.
Звісно, практично для всіх таких ситуацій було додано публічний API, за допомогою якого ви можете отримати такий доступ. Однак це все одно передбачає зміни коду. Крім того, у новій версії Java немає офіційної підтримки від Spring. Це не означає, що інструмент не працює, але офіційна гарантія тепер відсутня.
Головний недолік Java 17 — втрати часу. Адже якщо у вас об’ємний проєкт, то ви зіткнетеся з великою кількістю хай і маленьких, але проблем при переході на нову версію. Проте одразу наголошу: міграція з 11-ої на 17-ту версію все ж не настільки болісна, як було у часи з 8-ої на 11-ту.
Думаю, всі розробники добре пам’ятають цей не найкращий досвід. Адже там було дуже багато залежностей, які конфліктували між собою. Наприклад, найбільш яскравою проблемою мого особистого переходу стала бібліотека djkloyn
, яка з невідомих причин була несумісною з Worker Thread на Java 11. Через це мені взагалі довелося відмовитися від використання цієї бібліотеки в майбутньому.
Незважаючи на ці моменти, все одно думаю, що варто спробувати нову версію — недоліки не перевищують її переваги. Я особисто дуже радий нарешті перейти на Java 17. Вона краща і з точки зору швидкості, і з точки зору нових, реалізованих в ній функцій та мовних додатків (ті ж Sealed-класи та Records). Тож рекомендую всім переходити на Java 17 та не сидіти на застарілих версіях.
Що далі?
І наостанок — трохи слів про те, що нас чекає далі. Наступний крок для розробників Java заплановано на 20 вересня 2022 року, коли має вийти Java 19. Але пам’ятайте: це non-LTS-версія, в якій буде не так вже багато змін. Тому більше я б очікував на вересень 2023 року, коли має з’явитися наступна «повноцінна» LTS Java 21. У ній, напевно, буде чимало цікавого.
Я особисто чекаю на появу Project Loom. Давно стежу за цим проєктом. У ньому мають з’явитися віртуальні потоки. І нехай зараз у моїх проєктах не використовується багатопоточність, мені було б цікаво спробувати його на практиці. Адже для звичайних Java-користувачів Project Loom обіцяє легку багатопоточність без потреби переходу на іншу мову, використання бібліотеки або фреймворку.
Це вже звучить дуже непогано. Але найважливіше, як мені здається, очікує на розробників бібліотек, які постійно мають вирішувати проблему concurrency — знову, й знову, й знову… А з таким рішенням все це можна перекласти на JVM, як раніше робили з оптимізацією пам’яті (GC) та коду (JIT). Це має бути справжня революція.
Цей матеріал – не редакційний, це – особиста думка його автора. Редакція може не поділяти цю думку.
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: