Kurs Java

Nowa Java vs Lombok

Czy warto zawsze stawiać na najnowszą Javę? Dlaczego w dużych firmach rzadziej aktualizuje się jej wersje? Takie pytania padają co jakiś czas od naszych czytelników. Zwykle odpowiadamy na nie — "to zależy", przytaczając przy okazji kilka argumentów za, jak i kilka przeciw. Wszystko zależy w dużej mierze od konfiguracji naszych projektów oraz tego z ilu i z jakich zależności korzystają.

Na przykład, jeśli ktoś dopiero zaczyna swoją przygodę z Javą, to taka osoba całkiem chętnie ściągnie najnowszą wersję i będzie to optymalne rozwiązanie, ale jeśli ktoś programuje już zawodowo i korzysta w swoich projektach z wielu zależności takich jak Spring Framework czy Lombok, to taka osoba niekoniecznie musi się do tego spieszyć.

Dlaczego?

Odpowiedzią na to pytanie niech będzie opis problemu, na który natknęliśmy się w ostatnich dniach w jednym z naszych projektów. Podczas próby aktualizacji wersji Javy do Javy 17 okazało się, że projekt nie potrafił się skompilować, a standardowe procedury podniesienia zależności lub dokonania drobnych zmian w kodzie, okazały się nieskuteczne.
Appa Notka. Bardzo szybko okazało się, że przyczyną braku kompilacji jest konflikt między używanym przez nas w projekcie Lombokiem a nową wersją Javy.

Opis zagadnienia

Okazało się, że powodem braku kompilacji była lombokowa adnotacja @Builder.Default. Natomiast sam wyjątek prezentował się tak:
An exception has occurred in the compiler (17.0.1).
Please file a bug against the Java compiler via the Java bug reporting page
...

java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
    at jdk.compiler/com.sun.tools.javac.jvm.ClassWriter.writePosition(ClassWriter.java:672)
    at jdk.compiler/com.sun.tools.javac.jvm.ClassWriter.writeTypeAnnotation(ClassWriter.java:649)
    at jdk.compiler/com.sun.tools.javac.jvm.ClassWriter.writeTypeAnnotations(ClassWriter.java:553)
    at jdk.compiler/com.sun.tools.javac.jvm.ClassWriter.writeCode(ClassWriter.java:1120)
    at jdk.compiler/com.sun.tools.javac.jvm.ClassWriter.writeMethod(ClassWriter.java:988)
    at jdk.compiler/com.sun.tools.javac.jvm.ClassWriter.writeMethods(ClassWriter.java:1479)
    at jdk.compiler/com.sun.tools.javac.jvm.ClassWriter.writeClassFile(ClassWriter.java:1584)

...
Wszelkie próby podniesienie wersji Lomboka, czy też obniżenia wersji Javy na przykład do wersji 15 spaliły na panewce. Po głębszej analizie i przejrzeniu internetowych wpisów o podobnej tematyce okazało się, że ten konflikt między Javą a Lombokiem istnieje już od wersji 14!

Innymi słowy, bez stosowania wątpliwych workaroundów nie jesteśmy w stanie użyć Javy >= 14 w projekcie, w którym używamy wspomnianej adnotacji Lomboka.

Winna Java czy Lombok?

Zagadnienie to było opisywane i rozwiązane przez jednego z chińskich kontrybutorów Javy OpenJDK o wdzięcznie brzmiącym nicku — lgxbslgx. Co prawda problem leży na styku Lomboka i Javy, ale jednak lgxbslgx wykonał poprawkę po stronie Javy, dzięki czemu prawdopodobnie nie będzie potrzebna żadna poprawka ze strony deweloperów Lomboka.
Java CheckedException
Powyższa komunikacja z lipca wskazuje gdzie leży problem. Bez wchodzenia w zbędne detale, biblioteka Lomboka tworzy w kodzie nowe węzły JavacNode przy użyciu wewnętrznej metody kompilatora Javy, ale nie ustawia przy tym poprawnej pozycji pos. Dawniej ten fragment kodu działał, niemniej wraz z nowymi wersjami Javy przestało to funkcjonować.
Appa Notka. Powyższe zdjęcie pochodzi z wątku dostępnego pod linkiem "Wątek z wyjaśnieniem lgxbslgx" (link pod artykułem). W celu znalezienia wpisu, po przejściu na stronę, proponuję wyszukać słowo "JavacHandler".

Kiedy fix?

W tej sytuacji prawdopodobnie najlepszym rozwiązaniem będzie poczekanie na poprawkę dostępną w Javie 18 (już w marcu). Ewentualnie można też zarzucić sieci na wersję 17.0.2, która powinna zostać wypuszczona lada moment. Fix został wykonany przez lgxbslgx w komicie, który znajdziesz na Githubie pod linkiem podanym na dole strony.

Workaround

A co w przypadku gdy ktoś nie może czekać nawet jednego dnia na rozwiązanie problemu? Cóż zawsze można pokombinować z tymczasowym rozwiązaniem zastępczym, które oczywiście nie jest eleganckie, ale jakoś powinno pozwolić nam przetrwać. Osobiście, nie podoba mi się takie podejście i dlatego nawet nie sprawdzałem go dokładnie, ale wydaje się, że rozwiązanie podane przez jednego z programistów w sieci może się udać:
@Builder
class MyTestDto {
    // @Builder.Default
    private List<@Length String> footer = List.of();

    // See: https://github.com/projectlombok/lombok/issues/3065
    public static class MyTestDtoBuilder {
        private List<@Length String> footer = List.of();
    }
}
Pełny opis zagadnienia znajduje się w kolejnym linku na dole strony ("Workaround").

Podsumowanie

Tak jak widać, czasem podniesienie wersji Javy wcale nie jest takie proste, a przykład przytoczony w artykule nawinął się niejako "na dzień dobry". Według mnie, biorąc pod uwagę to, że Java nie wprowadza rewolucyjnych zmian od czasu popularnej ósemki, nie warto się spieszyć z aktualizacją. Oczywiście, jeśli ktoś bardzo potrzebuje świeżej wersji Javy, to zawsze może jej użyć, rozwiązując ewentualne problemy "szyciem na miarę". Trzeba jednak pamiętać, że w złożonych projektach takie podejście może być ryzykowne.
Autor: Jarek Klimas
Data: 07 stycznia 2022
Labele:Backend, Poziom średniozaawansowany, Java Linki
Link do komita z fixem w OpenJDK
Workaround
Wątek z wyjaśnieniem lgxbslgx
Masz swoje przemyślenia na temat artykułu? Podziel się nimi!
Masz pytanie odnośnie zagadnienia omawianego w artykule?
Coś, co napisaliśmy, nie zaspokoiło Twojego głodu wiedzy?
Daj nam znać co myślisz i skomentuj artykuł na facebooku!

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy: stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .


Pozycjonowanie stron: Grupa TENSE