Jako, że przez klika edycji zajmowaliśmy się dużymi zapowiedziami, w nowym wydaniu mamy sporą ilość releasów: Gradle, Wildfly, Resillience4j, Async-Profiler i Spring. Głównym daniem pozostaje jednak Feature Freeze dla nowej JDK 20.
1. Feature Freeze dla JDK 20 – co przyniesie nowa edycja?
Kiedy poprzednia Java składała się głównie z Preview, przyznam, że było w tym coś fascynującego. W końcu to właśnie JDK 19 pozwalało nam spojrzeć w przyszłość tego, jak rozwijać się będzie platforma w najbliższych latach i posmakować wyników kilku długo oczekiwanych projektów. Muszę jednak przyznać, że ciężko wykrzesać mi jest podobny entuzjazm w stosunku do JDK 20. Ponownie mamy do czynienia z zestawem Preview, ale są to w zasadzie drobne iteracje (z wyjątkami o których za chwilę) już istniejących API. A wraz z dzisiejszym dniem, nowa Java wchodzi w fazę Rampdown – oznacza ona, że lista funkcjonalności została zamrożona i nie można spodziewać się żadnych dalszych nowinek.
Finalnie więc lista nowości w JDK 20 prezentuje się więc następująco:
- 429: Scoped Values (Incubator)
- 432: Record Patterns (Second Preview)
- 433: Pattern Matching for switch (Fourth Preview)
- 434: Foreign Function & Memory API (Second Preview)
- 436: Virtual Threads (Second Preview)
- 437: Structured Concurrency (Second Incubator)
Jak widzicie, zupełnie nowych rzeczy jest jak na lekarstwo. I oczywiście, sam fakt, że API w wersji preview przechodzą zmiany jest czymś pozytywnym, a takie dodatki w Foreign Function & Memory API są całkiem przyjemne – o nich możecie przeczytać choćby u Pera Minborga, który opublikował tekst Java 20: A Sneak Peek on the Panama FFM API (Second Preview). Jeżeli jesteście zaś ciekawi szczegółów zmian w proposalach nowych rekordów i pattern matchingu, o Record Patterns (Second Preview) oraz Pattern Matching for switch (Fourth Preview) pisałem już w jednej z poprzednich edycji. Podobnie wygląda sytuacje nowych iteracji JEPów powiązanych z Loomem – Virtual Threads (Second Preview) oraz Structured Concurrency (Second Incubator), które również miałem okazję już opisać. Nie robię tego tu po raz kolejny, bo nowości są naprawdę raczej kosmetyczne.
Od tamtego czasu, 437: Structured Concurrency (Second Incubator) doczekała się jednak pewnej zmiany, którą można uznać za jedyny realnie interesujący dodatek wprowadzony w JDK 20 – wsparcie dla Scope Values. I nimi się właśnie teraz zajmiemy.
O Scope Values
Zapotrzebowanie na lokalne wartości wynika ze zmian wprowadzonych w JVM na potrzeby Loom. Ze względu na fakt, że Loom opiera się na bardzo leciutkich wątkach (dzięki czemu możliwe staje się tworzenie ich w zasadzie nieograniczonej ilości), musimy bardzo uważać na rozmiar struktur tworzonych na potrzeby każdego wątku (bardzo fajny artykuł na ten temat znaleźć możecie tutaj).
Popularne Thread Locals (zmienne przypięte do wątku) od początku były kamieniem w bucie twórców wirtuaknych wątków. Rozwiązaniem na nie mają być wspomniane Scope Values – efektywnie finalne, niemutowalne zmienne lokalne, które mogą być w ramach potrzeb bezpiecznie dzielone między wątkami, zmniejszając ilość niezbędnej pamięci. Każdy wątek-dziecko posiadać ma dostęp do pełnego kontekstu swojego rodzica. Pomysł realizacji tego zadania podkradziony został z Common Lispa i jego “zmiennych specjalnych”,
O Scope Values można myśleć jako niewidocznych parametrach, które są przekazywane do każdej metody. Mają one możliwość przypisania do zmiennej lokalnej wartości wyłącznie na potrzeby konkretnego zakresu (scope) – po jego zakończeniu wartości zmiennych w nim ustawionych zostanie automatycznie przywrócona. Zachowanie to pozwala np. na zakrycie wartości x
i y
, w którymś z “dzieci”, bez wpływu na wszystkie inne wątki je używające.
Dość dobrze obrazuje to kod źródłowy z JEPa:
final static ScopedValue<...> x = new ScopedValue<>();
final static ScopedValue<...> y = new ScopedValue<>();
{
ScopedValue.where(x, expr1)
.where(y, expr2)
.run(() -> ... code that uses x.get() and y.get() ...);
}
Jak widać, składnia przypomina trochę znane wszystkim “atomiki” na sterydach. Wartości x
i y
mogą być przekazywane z wątku “rodzica” do wątku “dziecka”. Metoda run()
„wiąże” zaś w tym przypadku x
i y
z wartościami expr1
i expr2
. Podczas wykonywania metody run()
wszelkie wywołania x.get()
i y.get()
zwracają właśnie je. Po jej opuszczeniu, wartości wracają do wersji poprzednich, odziedziczonych po rodzicu.
Oczywiście, jak to z Loomem bywa, składnia może się jeszcze wielokrotnie zmienić (zwłaszcza, że mamy do czynienia z niczym innym jak inkubacją). Nie ukrywam też, że moja sympatia do tego JEPa na pewno pochodzi z faktu, że podświadomie trochę jednak jestem kryptoclojurowcem, więc wszelkie nawiązania do Lispa w JDK przyjmuje z otwartymi ramionami.
Ogólnie wydaje mi się, że słowo klucz opisujące nowe wydanie Javy to „stabilizacja”. Co może być lepszym kierunkiem – wolę w następnym LTS dostać małą ilość stabilnych, dużych featury niż dużą ilość drobnicy. Na pewno cieszy mnie, że po dodaniu Scope Values, wirtualne wątki stają się coraz bardziej kompletne i użyteczne.
Zainstaluj teraz i czytaj tylko dobre teksty!
2. Release Radar – Gradle, Wildfly, Resillience4j, Async-Profiler i Spring
Dawno nie było Release Radaru, dlatego dzisiaj poświęcimy sporo miejsca premierą ostatnich tygodni – a takowych akurat było trochę.
Resilience4j 2.0
Były czasy, gdy król tak zwanego “Fault Tolerance” w ramach JVM był tylko jeden – tym światkiem niepodzielnie rządził Hystrix od Netflixa. W pewnym momencie jednak firma porzuciła projekt i w wyniku działań społeczności wyewoluował on w Resilience4j. O projekcie było ostatnio raczej cicho, ale stwierdziłem, że warto o nim przypomnieć, zwłaszcza, że pojawiła się dość dobra okazja – wydano wersje 2.0 projektu. Co się takiego wydarzyło, że zasłużyła ona na „duży” numer?
Poza wsparciem Java 17, Spring Boot 2.7 (szkoda, że nie od razu 3.0) oraz Kotlina 1.7.20, nowe Resilience4J to pewna istotna zmiana pod maską. Otóż projekt pozbył się dependencji na bibliotekę Vavr. Dla tych, którzy Vavra nie kojarzą, jest to zbiór funkcyjnych „utili”, trochę przypominający Guavę i Kotlin Arrow i swego czasu dość popularny. Sam projekt ma dość burzliwą historię, nazwał się kiedyś Javaslang, ale Oracle oskarżył twórców o łamanie ichniejszego trademarku na słowo Java, co wymusiła rebranding.
Twórcy Resilience4j postanowili pozbyć go z projektu, ponieważ nie wykorzystywali go aż tak ekstensywnie, a stanowił spory balast który rzutował na wszystkie projekty używające Resilience4j. Więcej kontekstu znajdziecie w Githubowej dyskusji.
A jako, że samym Resilience4j Java Developer nie żyje, jeśli chcecie dowiedzieć się więcej o rozwiązaniach do Fault Tolerance dostępnych w Javie zapraszam do lektury A tentative comparison of fault tolerance libraries on the JVM – bardzo dobrej przeglądówki od Nicolasa Fränkela.
Gradle 7.6
Kolejnym wydaniem, o którym chciałbym Wam dzisiaj opowiedzieć to nowe wydanie Gradle. Popularny Build Tool ma to do siebie, że wydania wypluwa dosyć regularnie, ale akurat praktycznie każde z nich wnosi coś ciekawego. Nie inaczej jest z najnowszą edycją 7.6.
To jest bowiem pierwszą edycją, która pozwala nam kompilować do Javy 19, w związku z tym jeśli do tej pory nie byliście w stanie przepiąć swoich produkcyjnych projektów na nowe Preview API (no bo tylko one się ostanio pojawiają), nareszcie Gradle już nie jest dla Was żadną przeszkodą. Gradle zresztą sobie to JDK samodzielnie pobierze dzięki wprowadzonemu już parę edycji temu Java Toolchain, który obecnie wsparty został o możliwość zdefiniowania konkretnego źródła, z którego chcemy JDK pobrać. Dlatego też użytkownicy DragonFly JDK albo Liberica JDK nie będą już skazani na Adoptium. A że wariantów JDK jest dużo (o czym przekonać się można choćby na stronie whichjdk.com, opisującej istniejące miedzy nimi różnice).
Fani silnego typowania i Kotlinowego DSL-a otrzymali zaś dużo lepsze podpowiadanie składni. Dodatkowo, usprawniona została inkrementalna kompilacja w sytuacji błędów, a dodatkowo umożliwiono też „rerun” pojedynczego taska. Ostatnią zaś dużą rzeczą jest możliwość podłączenia się do gradlowego debuggera nie tylko z lokalnej maszyny, ale również po sieci, co może być przydatne np. w środowiskach CI/CD.
WildFly 27
Przechodzimy dalej, tym razem mam coś dla użytkowników Jakarty EE. „Ten fajny” serwer aplikacyjny – WildFly.
Można się śmiać z powyższej zbitki, ale to właśnie WildFly ze wszystkich narzędzi mających jakiekolwiek powiązania z światem starej Java EE jest z pewnością tym w największym stopniu eksperymentującym z nowoczesnymi technologiami. Niech za przykład posłuży to, że nowe wydanie jest kompatybilne z świeżutką Jakarta EE 10 – i to również świeżo dodanym do niej Core Profilem, konkurencją dla MicroProfile. Już samo to zwiastowałoby ciekawe wydanie, ale WildFly 27 przynosi sporo więcej.
Po pierwsze, jest to kolejna z technologii mocno integrująca się z Micrometer, który otrzymał wsparcie, choć narazie tylko jako Tech Preview. WildFly mocno inwestuje również we wsparcie chmury i ogólnie bycie cloud-native. Świadczyć o tym może nie tylko dalszy aktywny rozwój „błogosławionych” obrazów Dockerowych, ale także nowa architektura dla WildFly S2I. Pod tym szalenie enigmatycznym skrótem kryje się WildFly Source-to-Image, czyli narzędzie do wdrażania aplikacji na serwery aplikacyjne w chmurze. S2I służy do metoda budowania powtarzalnych obrazów Docker bezpośrednio z kodu źródłowego. W nowym wydaniu WildFly zmieniona została architektura całego narzędzia. Zmian jest dużo, dlatego jeśli używacie S2I, polecam sprawdzić dedykowane temu narzędziu ogłoszenie.
Async-Profiler 2.9
Niedawno pisałem o narzędziu, jakim jest Async-Profiler w kontekście JEP 435: Asynchronous Stack Trace VM API, którego celem było ustandaryzowanie API dla Stack Trace maszyny wirtualnej. Dzisiaj przyszło mi do tematu wrócić, ponieważ najlepszy profiler JVM dostał nową wersję, a z nią jedną bardzo dużą zmianę: Heap Leak Profiler.
Za tą niepozorną nazwą kryje się bowiem potężne narzędzie, będące w stanie wykrywać wycieki pamięci w czasie rzeczywistym. Co ważne, całość została zaprojektowana w celu minimalnego narzutu na wykonywany proces, całość opiera się bowiem o próbkowanie danych, co znacznie zmniejsza zużycie zasobów. Dzięki temu całość nadaje się do wykrywania tego typu problemów w środowisku produkcyjnym.
Jeżeli jesteście ciekawi detali, całość została dobrze opracowana przez Krzysztofa Ślusarskiego w jego tekście Finding heap memory leaks with Async-profiler. Tam też znajdziecie konkretne przypadki użycia.
Spring Batch 5.0
A na końcu, wprawdzie o Springu już ostatnio było dużo, ale od tamtej pory pojawiły się dwie całkiem spore nowości.
Pierwszą z nich jest Spring Batch w wersji 5.0, który może pochwalić się dość imponującą ilością zmian. Jest to pakiet zapewnia funkcje potrzebne przy przetwarzaniu dużych ilości rekordów, takie jak logowanie, zarządzanie transakcjami, restartowanie i pomijanie jobów, a także zarządzanie zasobami.
Oczywiście, mamy do czynienia z wyrównaniem do obowiązujących wersji Spring Framework, więc w gratisie pojawiło się choćby wsparcie Jakarty EE 9 i GraalVM. Ten ostatni ze względu na charkaterystykę pracy Spring Batcha (działanie na wielu, ale krótko żyjących wątkach) może według zamieszczanych benchmarków pochwalić się przyspieszeniem nawet do dziesięciu razy. Pełną listę zmian (a jak wspominałem – jest ich trochę) zobaczyć możecie w oficjalnym ogłoszeniu.
Spring Integration 6.0
I na sam koniec Spring Integration 6.0. Spring Integration to framework do budowy szeroko rozumianych „integracji”, głównie w tym korporacyjnym wydaniu.
Poza standardowymi usprawnieniami, nowy Spring Integration to przede wszystkim wsp arcie dla GraphQL, który bazuje na projekcie spring-graphql. Oprócz tego fani Kotlina z pewnością ucieszą się z faktu, projekt może wreszcie pochwalić się wsparciem dla Korutyn. Większe lub mniejsze zmiany czy migracje dotknęły również integracji z większością providerów, takich jak Apache Camel (nowa integracja), Hazelcast, MQTT czy RabbitMQ.
Zainstaluj teraz i czytaj tylko dobre teksty!
3. Log4Shell – Pamiętamy 🕯️
Mija nam właśnie rok od jednego z największych incydentów w historii Javy, czyli tak zwanego Log4Shell – jeśli nie byliście wtedy z nami (szczęściarze) więcej przeczytacie tutaj. Wydaje mi się, że należy czcić jego pamięć w sposób godny takiej rocznicy, na przykład poprzez przypomnienie fali gorzkiego humoru, który towarzyszył społeczności w tych trudnych dniach.
Zatem niech poleci mój ulubiony, który dodatkowo stawia sprawę w nieco szerszym kontekście:
Log4Shell, zawsze będziesz w naszych sercach jako dzień, który zjednoczył Java Developerów na całym świecie we wspólnych emocjach (choćby emocji przerażenia i smutku) ❤️
Log4Shell, zawsze będziesz w naszych sercach jako dzień, który zjednoczył Java Developerów na całym świecie we wspólnych emocjach (choćby emocji przerażenia i smutku) ❤️
Więcej takowych znajdziecie na stronie log4jmemes.com – tyle tego było, że doczekały się swojego miejsca w sieci.