- Co nowego w javie
- Badania JetBrains
- Java 9, 10, 11, 12, 13, 14 i pomysły na rozwinięcie
- Problemy ze wsparciem dla paczek typu sun.misc.unsafe
- Nie zawsze update jest łatwy i bezbolesny
- Aktualizacja bibliotek
- Jdpes i jdeprscan
O nowościach w javie i migracji systemu PLM
W javie sporo się zmieniło. Od wydania najpopularniejszej jej wersji, czyli ósemki minęło już kilka dobrych lat. Według ostatniej ankiety przeprowadzonej przez firmę Jetbrains ( https://www.jetbrains.com/lp/devecosystem-2019/java/) ciągle wersja 8 jest tą, z której najczęściej korzystają developerzy. Czym jest to spowodowane? Mamy już przecież za sobą premierę Javy 13. Powodów może być kilka:
- Szybki cykl wydawniczy. Java jest teraz wydawana co pół roku – w okolicach kwietnia i marca. Natomiast wersja LTS (long time support) co 3 lata. Taka częstotliwość zmian powoduje, że nikt nie decyduje się na aktualizację co pół roku.
- Dużo projektów było rozpoczętych jakiś czas temu i przeważnie są napisane w Javie 8. Migracja do kolejnej wersji LTS może okazać się problematyczna i firmy nie chcą marnować pieniędzy na aktualizację. Aczkolwiek zaciąganie długu technicznego może okazać się w przyszłości zgubne.
- Uczelnie wyższe w programie nauczania raczej prowadzą zajęcia w Javie 8.
Źródło: https://www.jetbrains.com/lp/devecosystem-2019/java/ Wszystko to może zmienić się, kiedy skończy się oficjalne darmowe wsparcie dla Javy 8, czyli pod koniec 2020 roku.
Darmowa czy płatna?
Jakiś czas temu świat obeszła wiadomość o płatnej wersji Javy. Ostatecznie okazało się, że nie taki diabeł straszny jak mówią, i że nie ma się czego obawiać. Java od Oracle pozostaje dalej darmowa. Różnica występuje w magicznym słowie – support. Oracle rozwija język w dwóch dystrybucjach – Oracle JDK oraz OpenJDK. OracleJDK można używać bezpłatnie w celach niekomercyjnych. Do użytku komercyjnego trzeba mieć wykupioną licencję. Natomiast nic nie stoi na przeszkodzie, żeby używać OpenJDK, który jest całkowicie darmowy dla użytku komercyjnego. Jednakże w przypadku OpenJDK wparcie wynosi tylko 6 miesięcy.
Źródło: https://www.oracle.com/technetwork/java/java-se-support-roadmap.html
Koszty wersji z rozszerzonym wsparciem
Za każdy procesor na serwerze i instancjach chmurowych koszt wyniesie 25$. Natomiast za Javę zainstalowaną na komputerze użytkownika 2.5$ miesięcznie za użytkownika. Do wyboru są subskrypcje: jedno-, dwu- lub trzy- roczne.
O nowościach i ciekawych funkcjonalnościach
Dla niektórych nowości w Javie są równoznaczne z lambdami i streamami dodanymi w Javie 8. Nie zaprzeczam, że był to duży skok w rozwoju języka, ale od tamtego momentu zdążyło się już wiele wydarzyć, a zmiany z ósemki to już chleb powszedni. W artykule chciałbym, więc pokazać najważniejsze zmiany od Javy 9 do Javy 13, oraz te planowane w kolejnych wersjach. Oczywiście skupię się na najważniejszych aktualizacjach z punktu widzenia developera.
Java 9 Scalenie JDK oraz JRE
Przed tą wersją, rozróżnialiśmy JDK (Java Development Kit) oraz JRE (Java Runtime Environment). JDK zawierało w sobie JRE, ale również kompilator (javac) oraz różne narzędzia, takie jak: javadoc. Od Javy 9, otrzymujemy jedną paczkę – JDK – ze zmodyfikowaną, można powiedzieć “zmergowaną” strukturą katalogów wcześniejszych JRE i JDK. Najistotniejszą modyfikacją jest przeniesienie skompilowanego JDK (rt.jar) oraz narzędzi (tools.jar) w nieco zmienionej formie do katalogu lib.
Adnotacja @Deprecated
Została rozszerzona funkcjonalność adnotacji @Deprecated, dając nam więcej informacji o oznaczonym w ten sposób API (tj. polu, klasie czy metodzie). Możemy ustawić teraz dwa parametry, since – mówiący od które wersji Javy byt jest zdeprecjonowany oraz forRemoval – przyjmujący wartość logiczną true lub false (wartość domyślna). Jeśli API zostało oznaczone jako forRemoval=true, możemy się spodziewać, że kompletnie zniknie w kolejnym lub jednym z kolejnych wydań bez kompatybilności wstecznej! Dodatkowo otrzymaliśmy nowe narzędzie – jdeprscan – do analizowania naszego codebasu (pojedyńczych klas lub całych plików jar) pod kątem używania przestarzałego API. Z flagą jdeprscan –for-removal, polecenie zwróci tylko API oznaczone do usunięcia. Ciekawostka na temat tego narzędzia jest taka, że mając je (od JDK 9), jesteśmy w stanie przeskanować pliki skompilowane z wcześniejszymi wersjami Javy, a konkretnie od wersji 6+.
Moduły
Java 9 wprowadziła nowy poziom abstrakcji powyżej pakietów. Moduł to kolejny stopień enkapsulacji. Można go postrzegać jako zbiór ściśle związanych ze sobą pakietów. Prace nad modułowością trwały wiele lat pod nazwą Projekt Jigsaw. Głównym założeniem było umożliwienie szybszego rozwoju języka. Dzięki podziałowi całego JDK na wiele modułów, stało się to możliwe (prawdopodobnie to Jigsaw był jednym z powodów nowego, szybszego cyklu wydań).
Co daje nam moduł? Moduł jako pojemnik na pakiety, jest warstwą umożliwiającą kontrolę dostępu do swojej zawartości. W uproszczeniu, ukrywa całe zawarte API przed innymi modułami. Dopiero jawne zadeklarowanie w tzw. deskryptorze modułu pozwala udostępnić nam wybrane API na zewnątrz.
Subiektywnie najważniejszą rzeczą dla developera z całej wiedzy o modularyzacji powinna być nowa drabinka poziomów dostępu do API.
Jlink
JLink jak na obrazku, pozwala skurczyć naszą Javę. Jest to narzędzie za pomocą którego można “uszyć” customowe JRE pod wybrany program. Zamiast wykorzystywania całego JDK, składane jest środowisko uruchomieniowe tylko z modułów, które faktycznie są używane w naszej aplikacji. Stworzone i dostarczone w ten sposób JRE jest w stanie wykonać naszą aplikację bez preinstalowania całego JDK. Utworzone w ten sposób customowe JRE do prostego HellowWorlda, ważą ~40MB zamiast 300MB (waga ostatniego JDK).
Java w konsoli
Tak to możliwe dzięki JShellowi. Jest to mechanizm znany w wielu innych językach pod nazwą REPL (Read-Eval-Print Loop – proste, interaktywne środowisko programowania. Użytkownik może wprowadzić polecenie, które natychmiast zostaje wykonane a jego wynik wyświetlony na ekranie.
Czy w ogóle warto poznać to narzędzie?
Istnieje kilka dziedzin w których JShell może się sprawdzić. Moim numerem jeden jest nauka osób początkujących podstaw programowania. Dzięki prostemu jshell -> enter, nie musimy rozpoczynać od uruchamiania ciężkiego IDE z wieloma ikonkami, kilkoma oknami i pewnie setkami zbędnych na początku funkcji. Jedynie zaciemniałoby to całokształt. Poza tym spróbujcie zupełnie nowej w świecie programowania osobie wytłumaczyć, co to jest to public static void main czy public class. Zaczynanie od obiektywności nie jest najlepszym pomysłem.
Dzięki REPL-owi, możemy zacząć od prawdziwych podstaw. 2+2 -> enter przypisuje nam wynik wyrażenia do automatycznie generowanych zmiennych $1, $2 itd. Oczywiście możemy deklarować własne zmienne int i = 2+2 -> enter. A podgląd wszystkich do tej pory wygenerowanych zmiennych uzyskały za pomocą komendy vars. W podobny sposób, lecz jednak z pełna sygnaturą, możemy generować metody i klasy. I tutaj ciekawostka, możemy deklarować elementy korzystające z nieistniejących jeszcze typów. Tak utworzona metoda lub klasa po prostu nie może zostać użyta do momentu zdefiniowania wszystkich zależności.
Java 10 : Var – local variable type inference – czyli wnioskowanie typu zmiennej lokalnej
Podobne rozwiązania pojawiły się już w innych językach, np. auto z C++. Zmiana ta umożliwia pisanie kodu z “ukryciem” jego typu w kodzie źródłowym, np. Nasza zmienna exampleVariable ciągle będzie miała typ String i nie możemy w kolejnych linijkach kodu przypisać do takiej zmiennej innego typu danych np. Integera’a. Takich zmiennych “varowych” należy jednak używać z rozwagą. Uważam, że nie należy zaciemniać kodu niepotrzebnym skracaniem nazwy typu – tzn. lepiej zapisać standardowego “Stringa” niż ciągle używać “vara”. Jest natomiast kilka przypadków, w których śmiało można wykorzystać zalety nowej funkcjonalności:W przypadku zagnieżdżonych kolekcji var sprawdza się to znakomicie – skraca nam kod oraz pozbywa się ciężkiej do rozczytania (na pierwszy rzut oka) konstrukcji. Var niesie ze sobą również pewne ograniczenia. Oto kilka z nich:
- można go stosować tylko do zmiennych lokalnych w metodzie (nie zadziała dla pola w klasie),
- nie możemy do niego przypisać wartości null (ponieważ null nie ma typu),
- Java ciągle jest językiem silnie typowanym, a var jest tylko ułatwieniem,
- dla wstecznej kompatybilności ciągle możemy nazywać swoje zmienne nazwą var, czyli możliwa jest następująca konstrukcja: var var = method(); .
Oprócz ograniczeń dostajemy również nowe możliwości. Var otwiera nam drogę do jednej sztuczki, której nie dało się wykonać wcześniej. Jest to sztuczka, której lepiej nie używać na swoim projekcie, ponieważ delikatnie zaciemnia nam czytelność kodu. Aczkolwiek warto wiedzieć, że taka możliwość istnieje. Mowa tutaj o dodawaniu pól i metod w sposób ad hoc do istniejącej klasy. Nie musimy tworzyć nowych plików źródłowych z klasami, które dziedziczyłyby celem rozszerzenia istniejącej. Można do tego celu użyć klas anonimowych i naszego “vara”:
Java 11 (LTS): Uruchamianie programu z kodu źródłowego
Pierwszy LTS w nowym cyklu wydań umożliwia bezpośrednie wykonywanie kodu źródłowego za pomocą interpretera. Kod źródłowy jest kompilowany do pamięci, a następnie wykonywany przez interpeter. Ograniczeniem jest to, że wszystkie klasy muszą być zdefiniowane w tym samym pliku. Tym samym nie powinniśmy zostawać tego rozwiązania przy obszerniejszych programach.
Funkcjonalność ta jest szczególnie przydatna dla osób początkujących, które chcą wypróbować napisane przez siebie proste aplikacje. Wraz z jshell’em będzie to doskonały zestaw narzędzi dla osób zaczynających naukę języka Java.
Przykład “Witaj Świecie”.
Umieszczamy swój kod w pliku z rozszerzeniem .java.
Następnie uruchamiamy nasz program za pomocą komendy:
Dodatkowo możemy użyć tego polecenia w konfiguracji z flagą –source. Umożliwia ona uruchomienie naszego kodu w zgodności z konkretną wersją Javy (Java 7 i nowsze). Dodatkowo można użyć tej flagi w sytuacji kiedy plik źródłowy ma inne rozszerzenie niż .java (lub nie ma żadnego).
Jeśli zapisalibyśmy nasz kod w pliku WitajSwiecie.app, to komenda wyglądała by następująco:
Wbudowany HTTP Client
Do momenty wydania Javy 11 mieliśmy w JDK bardzo słabe API do zapytań http. Z klasą
HttpURLConnection było bardzo wiele problemów. Miedzy innymi nie wspierała protokołu http/2, miała wiele nieudokumentowanych zachowań, działała blokująco (jedno zapytanie na jeden wątek), istniała w Javie od wersji JDK 1.1, a jej utrzymanie stało się bardzo ciężkie. Jako alternatywę mogliśmy wykorzystać jedną z wielu zewnętrznych bibliotek.
Ze względu na słabe standardowe API i częstą potrzebę dodawania zewnętrznych zależności (w końcu ile większych aplikacji nie potrzebuje wysłać zapytania http?) postanowiono ustandaryzować i wprowadzić nowego HTTP Client’a prosto do JDK.
Jego API jest naprawdę przejrzyste, a wykonanie pełnoprawnego zapytania http sprowadza się do kilku linijek kodu:
Rozszerzenie klasy String
Dostaliśmy również zestaw nowych metod w klasie java.lang.String:
- strip – ulepszona wersja metody trim, która istnieje od początków javy, od czasów kiedy standardy znaków nie były tak bardzo rozwinięte jak dzisiaj. Trim po prostu wycinał wszystkie znaki, których kod (wartość decymalna) była równa lub mniejsza od 32 (znak spacji). Strip wycina faktycznie wszystkie białe znaki, które w dzisiejszych standardach występują również na dalszych pozycjach.
- stripLeading oraz stripTrailing – bliźniacze metody, działają podobnie do strip, jednak wycinają białe znaki tylko odpowiednio z początku i z końca:
- isBlank – zwraca true jeśli String składa się wyłącznie z samych białych znaków.
- lines – konwertuje pojedynczy ciąg w Stream obiektów typu String, gdzie każdy kolejny obiekt jest pojedynczą linią z początkowego ciągu. Przydatne kiedy istnieje potrzeba wykonania operacji dla każdej linii osobno, a nie dla całego tekstu.
Nowe metody wejścia/wyjścia
Pojawiły się również dwie bardzo praktyczne statyczne metody w klasie FIles:
- writeString – pozwala na szybki zapis Stringa do pliku.
- Files.readString – odwrotność pierwszej metody, pozwala na łatwy odczyt pliku, zwraca zawartość w postaci obiektu String. Bardzo praktyczne okazuje się jej połączenie z metodą lines z klasy String. Można odczytać plik i od razu zinterpretować go linia po linii.
Java 12
Wydana w marcu 2019 wprowadza jedną bardzo ciekawą zmianę – switch expressions. Czyli małą rewolucję na istniejącej konstrukcji switch-case. Funkcjonalność ta jest dostępna jako tzw. preview feature.
Preview feature?
Są to takie funkcjonalności języka które musimy “odblokować”. Preview feature może zostać zmienione lub wycofane w następnych wersjach języka, więc należy uważać z używaniem takich funkcjonalności w kodzie produkcyjnym. Odblokować preview feature można poprzez dodanie flagi -enable-preview przy kompilacji i uruchamianiu programu.
IntelliJ może nas w tym wyręczyć, ponieważ w project structure znajdują się gotowe konfiguracje z różnymi poziomami języka, uwzględniającymi też preview features.
Switch Expression
W switch expressions dostajemy nową składnie dla starego i poczciwego switch-case’a. Dla wstecznej kompatybilności obie formy składni są poprawne, z tym że jeśli zdecydujemy się na jeden sposób zapisu to musimy go kontynuować w obrębie jednego switch case’a.
To co rzuca się w oczy to składnia przypominająca trochę składnie lambd. Można również zauważyć, że nie ma break’ów po każdym case. Nowa składnia zapewnia nam brak tzw. fall through – kod z następnych case’ów nie zostanie wykonany pomimo braku słowa kluczowego break.
Poza zmianą składni i konstrukcji. Switch ze “statement” stał się “expression”. Jaka jest różnica pomiędzy takimi tworami? Najprościej – “statement nie zwraca wartości a expression zwraca.
Statement jest na przykład konstrukcją if-else. Skoro nowy switch zwraca nam jakąś wartość to można taką wartość przypisać do zmiennej. Jeśli case jest jednolinijkowy to ze switcha zostanie zwrócona wartość zwracana przez to wyrażenie. Jeżeli chcielibyśmy wynik z wykonania “starego” switch’a przypisać do zmiennej, to musielibyśmy stworzyć zmienną przed switch’em, a następnie przypisywać do niej wartość w każdym case. Wygląda to tak:
Z użyciem nowej konstrukcji można to znacząco skrócić oraz uczynić o wiele bardziej czytelnym:
Wspominałem już o tym, że jeśli wyrażenie w case ma jedną linijkę to jego wynik zostanie zwrócony. Jeśli natomiast chcielibyśmy zawrzeć jakąś dłuższą logikę, to podobnie do lambd musimy nasz blok kodu obtoczyć nawiasami klamrowymi. Na samym końcu użyjemy słowa kluczowego break ze zwracaną wartością. Jest to dość niecodzienne rozwiązanie i może wyglądać trochę dziwnie. Dlaczego nie słowo kluczowe return? Return jest używany do zwrócenia wartości z całej metody, więc takie rozwiązanie byłoby nieintuicyjne.
Switch Expression – exhaustiveness
Zmieniło się również pod kątem sprawdzenia czy wszystkie możliwe wartości w case zostały obsłużone. W poprzednich wersjach Javy kompilator nie dbał o to czy w kodzie źródłowym były sprawdzone wszystkie ścieżki. Jedynie IDE i narzędzia typu sonar lint podpowiadały, że czegoś nam może w danym miejscu brakować. Kompilator generował jedynie ostrzeżenie. W Javie 12 taka sytuacja wygeneruje nam błąd kompilacji.
Java 13: Text Blocks
Bloki tekstu są kolejnym preview feature’m. Stanowią one ułatwienie dla dużych bloków tekstu, które musimy wkleić do kodu i przypisać do String’a. Aktualnie aby wkleić taki duży blok musimy każdą linijkę konkatenować lub zapisać cały blok w jednej linijce, używając co jakiś czas znaku nowej linii – “\n”. Z pomocą przychodzi nam oczywiście IDE, które potrafi wygenerować konkatenacje i znaki nowej linii, lecz ciągle taki zapis może być bardzo nieczytelny i po prostu nieelegancki.
Czym są i co dają nam bloki tekstu w Javie?
- Zwiększają czytelność kodu.
- Ułatwiają programowanie.
- Blok tesktu ciągle jest typu string.
- Nie należy mylić text block z raw string.
- Używają operatora potrójnego cudzysłowia – “””
Poniżej kilka przykładów bloków tekstu:
HTML
SQL
JSON
Razem z text blocks dodano do klasy string nowe metody. Warto zaznaczyć, że wszystkie są oznaczone jako deprecated for removal. Spowodowane jest to tym, że text blocks zostało wprowadzone jako preview feature.
- String::stripIndent() – wyrzuca z text bloku przypadkowe spacje które mogliśmy tam wpisać.
- String::translateEscapes() – zmienia znaki specjalne typu \b \n \t na ich kodowanie w unicode.
- String::formatted(Object…args) – odpowiednik String.format(), różnica jest taka że String.format() jest metodą statyczną, a formatted nie jest.
Więcej można znaleźć w oficjalnym opisie JEP’a – https://openjdk.java.net/jeps/355
Switch Expression Update
W Javie 13 mamy po raz kolejny do czynienia ze switch expressions, które ciągle jest preview feature. Ta wersja Javy wprowadza do jedną małą zmianę do jej funkcjonalności. Jak wcześniej wspominałem do zwrócenia wartości z case’a musieliśmy użyć słowa kluczowego break. Natomiast teraz mamy nieco czytelniejsze i mniej zaskakujące rozwiązanie. Twórcy języka wprowadzili nowe słowo kluczowe – yield izastępuje ono poprzedniego break’a.
New Socket API
Zmianą raczej mało widoczną z perspektywy programisty lecz bardzo istotną z kilku innych powodów jest przepisanie i odmłodzenie API Socketów. Zaimplementowane od nowa zostały klasy z pakietu java.net, a w szczególności klasa java.net.ServerSocket. Nowa implementacja jest całkowicie kompatybilna z poprzednim API. Dlaczego postanowiono na przepisanie socketów? Jest kilka powodów, a oto niektóre z nich:
- Implementacja socketów pochodziła z czasów JDK 1.0
- Sockety były mieszanką kodu z JDK1.0 i języka C, bardzo utrudniało to debugowanie kodu
- Istotne dla projektu Loom ( https://openjdk.java.net/projects/loom/) – projekt wprowadza do Javy koncepcję lekkich wątków – włókien (fibers)
Java 14
New NullPointerException
Postanowiono w końcu wziąć na warsztat źródło większości problemów generowanych przez aplikacje napisane w Javie – czyli null pointer exception. Nowa wersja najpopularniejszego wyjątku została trochę podrasowana. Nowy NPE pokazuje nam w swoim stack trace dokładną lokalizację wyjątku. W porównaniu do dobrze znanego NPE pokazuje on jaki obiekt wywołał nasz NPE, a nie tylko linijkę kodu, w którym wystąpił wyjątek. Jest to dosyć spore ułatwienie dla początkujących programistów, którzy mogą mieć problemy ze zrozumieniem NPE. Funkcjonalność ta znajduje swoje duże zastosowanie podczas długiego ciągu wywołań metod. Na pierwszy rzut oka nie za bardzo widać co spowodowało wyjątek, a żeby się tego dowiedzieć potrzebny byłby debuger. Nowy NullPointerException wygląda mniej więcej tak:
What’s next?
Oczywiście opisane tutaj zmiany nie są wszystkimi, nad którymi aktualnie pracują twórcy języka. Jest mnóstwo funkcjonalności, które są w fazie rozwoju, a nie zostały jeszcze zapowiedziane na konkretną wersję Javy.
Krótka historia aktualizacji systemu PLM do javy 11 Motywacja?
Po przekalkulowaniu kosztów kupna rozszerzonego wsparcia dla Javy 8 klient zdecydował się na migrację dużego systemu PLM do kolejnej wersji LTS – Javy 11. Aktualizacja tak wielkiego produktu nie jest łatwym przedsięwzięciem, ze względu na milionową ilość linijek kodu oraz długi rozwój (kilkanaście lat) aplikacji. Z powodu ogromnej złożoności aplikacji, natknęliśmy się na kilka ciekawych i niecodziennych przypadków, które można wziąć pod uwagę pod kątem aktualizacji tak dużego produktu.
Odpowiedzialność zespołu
Nasz zespół był w głównej mierze odpowiedzialny za aktualizacje i sprawdzenie wsparcia oraz kompatybilności bibliotek używanych przez system. Naszą pracę rozpoczęliśmy od skatalogowania wszystkich bibliotek, sprawdzenia ich ostatnich dat aktualizacji oraz tego czy są kompatybilne z nową wersją Javy. Niektóre z tych informacji wymagały kontaktu z twórcami bibliotek. Okazało się, że kilka bibliotek sprawiło nam problem swoim brakiem kompatybilności. W takim wypadku konieczna była aktualizacja do najnowszej wersji biblioteki (o ile istniała). Jeśli nie to należało znaleźć jakiś zamiennik.
Użyteczne narzędzia
Cała analiza bibliotek byłaby bardzo trudna bez odpowiednich narzędzi. Na szczęście istnieje kilka gotowych rozwiązań które okazują się być bardzo przydatne.
Jdeps & jdeprscan
Na początek wystarczą narzędzia, które są dostępne razem z JDK. Jdeps służy nam do analizy zależności naszych klas. Szczególnie przydatna w ramach nowej Javy przydaje się flaga -jdkinternals. Efektem wykonania komendy jdeps -jdkinternals jararchive.jar będzie lista wszystkich klas, które używają wewnętrznego API Javy. Generalnie żadna biblioteka nie powinna używać kodu przeznaczonego tylko do użytku wewnątrz Javy. Niestety tak kolorowo nie jest i przez lata wiele bibliotek śmiało korzystało z pakietów takich jak np. sun.misc.* Jeśli taka komenda nie zwróci nam żadnego wyniku oznacza to, że archiwum jar jest “czyste” pod względem używania wewnętrznego API Javy.
W przypadku biblioteki jmockit okazuje się, że jedna klasa korzysta z pakietu sun.reflect. Jdeps zwraca nam dosyć szczegółowy opis zależności oraz otrzymujemy link z sugerowanym zamiennikiem.
Kolejną użyteczną komendą jest jdeprscan. Szczególnie użyteczny w połączeniu z przełącznikiem -for-removal. Narzędzie to pokazuje nam wszystkie użycia zdeprecjonowanego API przez dane archiwum JAR. Pokazywane są jedyne zdeprecjonowane użycia metod z JDK. Nie możemy tego użyć do sprawdzenia pod względem zdeprecjonowania w 3rd party jar. Taką funkcjonalność zapewniają nam inne narzędzia, o których później. Ciekawym pomysłem jest również przełącznik –release, który pozwala nam na wybranie wersji Javy pod kątem, której będziemy sprawdzać zdeprecjonowane API, więc używając w jednym terminalu np. Javy 13, ciągle mamy możliwość sprawdzenia zdeprecjonowanie pod kątem Javy 11.
JAPICC
Czyli Java API compliance checker jest to opensourcowy projekt napisany w języku Perl. który służy do porównywania API dwóch różnych wersji bibliotek. Narzędzie generuje nam raport w HTML’u, który pozwala na łatwe przeglądanie zmian.
Aby zainstalować narzędzie należy zrobić clone oficjalnego repozytorium i uruchomić program make.
Natomiast przykładowe użycie narzędzia wygląda w taki sposób:
Więcej o JAPICC’u można się dowiedzieć na githubie: https://github.com/lvc/japi-compliance-checker
Jdiff
Narzędzie z którego raczej nie korzystaliśmy, ale natknęliśmy się podczas trwania projektu. Zapewnia podobną funkcjonalność co JAPICC. Przykładowe raporty z JDiff’a można znaleźć w repozytorium Guavy – https://guava.dev/releases/28.1-jre/api/diffs/
Api laboratory
Jeśli nie mamy ochoty instalować żadnego nowego oprogramowania to zawsze możemy skorzystać z aplikacji webowej. ABI Laboratory (https://abi-laboratory.pro/) jest ciekawym rozwiązaniem, które agreguje w sobie rozwiązanie poprzednie. Jedną dużą wadą jest to, że znajdziemy tam najpopularniejszebiblioteki open source. Celem sprawdzenia tych mniej popularnych należy skorzystać z dedykowanego oprogramowania.
W jaki sposób nowości z Javy pomogły nam w projekcie?
Z racji, że projekt zakładał migracje, to nie mieliśmy za wielkiego pola manewru, jeśli chodzi o nowe funkcje języka. Bardziej należało się skupić na kompatybilności API oraz wsparcia dla bibliotek 3rd party. Nowości w javie miały wpływ na pisanie szybkich aplikacji do automatyzacji pewnych czynności. Bardzo użyteczne okazały się nowe metody na klasie String i Files.
Jednoplikowe programy są funkcjonalnością do napisania aplikacji generujacej szybkie raporty, które można następnie podpiąć do pipeline. Jesteśmy przekonani, że migracja takich systemów jest bardzo dobrym rozwiązaniem. Im mniejszy dług technologiczny jest zaciągany tym łatwiej później jest utrzymać system.