Modułowość w Javie 9: Łączenie się z Project Jigsaw, Penrose i OSGi

Ten artykuł zawiera przegląd propozycji, specyfikacji i platform mających na celu uczynienie technologii Java bardziej modułową w Javie 9. Omówię czynniki wpływające na potrzebę bardziej modułowej architektury Java, krótko opiszę i porównam proponowane rozwiązania, i przedstawić trzy aktualizacje modułowości zaplanowane dla Java 9, w tym ich potencjalny wpływ na rozwój Javy.

Dlaczego potrzebujemy modułowości Java?

Modułowość to koncepcja ogólna. W oprogramowaniu odnosi się do pisania i wdrażania programu lub systemu komputerowego jako wielu unikalnych modułów, a nie jako pojedynczy, monolityczny projekt. Następnie używany jest znormalizowany interfejs, aby umożliwić komunikację modułów. Dzielenie środowiska konstrukcji oprogramowania na odrębne moduły pomaga nam zminimalizować sprzężenia, zoptymalizować tworzenie aplikacji i zmniejszyć złożoność systemu.

Modułowość umożliwia programistom przeprowadzanie testów funkcjonalności w izolacji i angażowanie się w równoległe prace programistyczne podczas danego sprintu lub projektu. Zwiększa to wydajność w całym cyklu życia oprogramowania.

Niektóre cechy charakterystyczne oryginalnego modułu to:

  • Autonomiczna jednostka rozmieszczenia (luźne sprzężenie)
  • Spójna i niepowtarzalna tożsamość (identyfikator i wersja modułu)
  • Łatwo zidentyfikowane i odkryte wymagania i zależności (standardowy czas kompilacji i ułatwienia wdrażania oraz metainformacje)
  • Otwarty i zrozumiały interfejs (umowa komunikacyjna)
  • Ukryte szczegóły implementacji (hermetyzacja)

Systemy zbudowane w celu wydajnego przetwarzania modułów powinny wykonywać następujące czynności:

  • Obsługa modułowości i wykrywania zależności w czasie kompilacji
  • Wykonuj moduły w środowisku wykonawczym, które umożliwia łatwe wdrażanie i ponowne wdrażanie bez przestojów systemu
  • Wdrażaj przejrzysty i niezawodny cykl życia wykonania
  • Zapewnij narzędzia ułatwiające rejestrację i wykrywanie modułów

Wszystkie rozwiązania zorientowane obiektowo, zorientowane na komponenty i zorientowane na usługi starają się zapewnić czystą modułowość. Każde rozwiązanie ma jednak swój własny zestaw dziwactw, które uniemożliwiają mu osiągnięcie modułowej perfekcji. Rozważmy pokrótce.

Klasy i obiekty Java jako konstrukcje modułowe

Czy obiektowa natura Javy nie spełnia wymagań modułowości? W końcu programowanie obiektowe w Javie kładzie nacisk na, a czasem wymusza unikalność, hermetyzację danych i luźne powiązania. Chociaż te punkty to dobry początek, zwróć uwagę na wymagania dotyczące modularności, które nie są spełnione przez zorientowaną obiektowo strukturę Java: tożsamość na poziomie obiektu jest zawodna; interfejsy nie są wersjonowane: a klasy nie są unikatowe na poziomie wdrożenia. Luźne powiązanie jest najlepszą praktyką, ale z pewnością nie jest egzekwowane.

Ponowne użycie klas w Javie jest trudne, gdy zależności innych firm są tak łatwo nadużywane. Narzędzia czasu kompilacji, takie jak Maven, starają się rozwiązać ten problem. Konwencje i konstrukcje językowe po fakcie, takie jak wstrzykiwanie zależności i odwrócenie kontroli, pomagają programistom w naszych próbach kontrolowania środowiska wykonawczego i czasami kończą się powodzeniem, zwłaszcza jeśli są używane z zachowaniem ścisłej dyscypliny. Niestety, sytuacja ta pozostawia tworzenie środowiska modułowego w gestii zastrzeżonych konwencji i konfiguracji ram.

Java dodaje również przestrzenie nazw pakietów i widoczność zakresów jako sposób tworzenia modularnych mechanizmów kompilacji i wdrażania. Ale te funkcje językowe można łatwo ominąć, jak wyjaśnię.

Pakiety jako rozwiązanie modułowe

Pakiety próbują dodać poziom abstrakcji do środowiska programowania Java. Zapewniają narzędzia do tworzenia unikalnych przestrzeni nazw kodowania i kontekstów konfiguracji. Niestety, konwencje dotyczące pakietów można łatwo obejść, co często prowadzi do powstania środowiska niebezpiecznych sprzężeń w czasie kompilacji.

Obecny stan modularności w Javie (poza OSGi, który omówię wkrótce) jest najczęściej osiągany przy użyciu przestrzeni nazw pakietów, konwencji JavaBeans i zastrzeżonych konfiguracji frameworków, takich jak te znalezione w Spring.

Czy pliki JAR nie są wystarczająco modułowe?

Pliki JAR i środowisko wdrażania, w którym działają, znacznie poprawiają się w porównaniu z wieloma starszymi konwencjami wdrażania dostępnymi w innym przypadku. Jednak pliki JAR nie mają żadnej wewnętrznej wyjątkowości, poza rzadko używanym numerem wersji, który jest ukryty w manifeście .jar. Plik JAR i opcjonalny manifest nie są używane jako konwencje modularności w środowisku wykonawczym Java. Zatem nazwy pakietów klas w pliku i ich udział w ścieżce klas są jedynymi częściami struktury JAR, które nadają modułowości środowisku wykonawczemu.

Krótko mówiąc, pliki JAR są dobrą próbą modularyzacji, ale nie spełniają wszystkich wymagań dla prawdziwie modułowego środowiska. Struktury i platformy, takie jak Spring i OSGi, używają wzorców i ulepszeń specyfikacji JAR, aby zapewnić środowiska do budowy bardzo wydajnych i modułowych systemów. Jednak z biegiem czasu nawet te narzędzia ulegną bardzo niefortunnemu efektowi ubocznemu specyfikacji JAR JAR Hell!

Classpath / JAR piekło

Gdy środowisko wykonawcze Java pozwala na dowolnie złożone mechanizmy ładowania plików JAR, programiści wiedzą, że są w piekle ścieżki klas lub piekle JAR . Szereg konfiguracji może prowadzić do tego stanu.

Najpierw rozważmy sytuację, w której programista aplikacji Java dostarcza zaktualizowaną wersję aplikacji i spakował ją w pliku JAR o dokładnie takiej samej nazwie jak stara wersja. Środowisko wykonawcze programów Java nie udostępnia żadnych narzędzi do sprawdzania poprawności określania poprawnego pliku JAR. Środowisko wykonawcze po prostu załaduje klasy z pliku JAR, które znajdzie jako pierwsze lub które spełnia jedną z wielu reguł ścieżki klas. Prowadzi to w najlepszym przypadku do nieoczekiwanego zachowania.

Kolejne wystąpienie piekła JAR pojawia się, gdy dwie lub więcej aplikacji lub procesów zależy od różnych wersji biblioteki innej firmy. Korzystając ze standardowych narzędzi do ładowania klas, tylko jedna wersja biblioteki innej firmy będzie dostępna w czasie wykonywania, co prowadzi do błędów w co najmniej jednej aplikacji lub procesie.

W pełni funkcjonalny i wydajny system modułów Java powinien ułatwiać rozdzielanie kodu na odrębne, łatwe do zrozumienia i luźno powiązane moduły. Zależności powinny być jasno określone i ściśle egzekwowane. Powinny być dostępne urządzenia umożliwiające modernizację modułów bez negatywnego wpływu na inne moduły. Modułowe środowisko wykonawcze powinno umożliwiać konfiguracje specyficzne dla określonej domeny lub rynku wertykalnego, zmniejszając w ten sposób czas uruchamiania i wpływ systemu na środowisko.

Rozwiązania modułowe dla języka Java

Oprócz wspomnianych do tej pory funkcji modułowości, ostatnie wysiłki dodają kilka innych. Następujące funkcje mają na celu optymalizację wydajności i umożliwienie rozszerzenia środowiska wykonawczego:

  • Segmentowany kod źródłowy : kod źródłowy podzielony na odrębne segmenty w pamięci podręcznej, z których każdy zawiera określony typ skompilowanego kodu. Cele obejmują pomijanie kodu niebędącego metodą podczas czyszczenia pamięci, kompilacji przyrostowych i lepszego zarządzania pamięcią.
  • Wymuszanie czasu kompilacji : konstrukcje językowe wymuszające przestrzenie nazw, przechowywanie wersji, zależności i inne.
  • Możliwości wdrażania : obsługa wdrażania skalowanych środowisk wykonawczych zgodnie z określonymi potrzebami, takimi jak środowisko urządzeń mobilnych.

Szereg specyfikacji i struktur modularności starało się ułatwić te funkcje, a kilka z nich niedawno awansowało na szczyt w propozycjach Java 9. Przegląd propozycji modułowości Java znajduje się poniżej.

JSR (Żądanie specyfikacji Java) 277

Obecnie nieaktywny jest Java Specification Request (JSR) 277, Java Module System; wprowadzone przez firmę Sun w czerwcu 2005 r. Ta specyfikacja obejmowała większość tych samych obszarów, co OSGi. Podobnie jak OSGi, JSR 277 również definiuje wykrywanie, ładowanie i spójność modułów, z rzadką obsługą modyfikacji w czasie wykonywania i / lub sprawdzania integralności.

Wady JSR 277 obejmują:

  • Brak dynamicznego ładowania i wyładowywania modułów / pakietów
  • Brak kontroli w czasie wykonywania pod kątem unikalności przestrzeni klas

OSGi (inicjatywa Open Service Gateway)

Platforma OSGI, wprowadzona przez OSGI Alliance w listopadzie 1998 r., Jest najczęściej stosowaną odpowiedzią na pytanie o modułowość na formalne, standardowe pytanie dotyczące języka Java. Obecnie w wersji 6 specyfikacja OSGi jest szeroko akceptowana i używana, zwłaszcza ostatnio.

Zasadniczo OSGi jest systemem modułowym i platformą usługową dla języka programowania Java, która implementuje kompletny i dynamiczny model komponentów w postaci modułów, usług, pakietów, które można wdrożyć i tak dalej.

Podstawowe warstwy architektury OSGI są następujące:

  • Środowisko wykonawcze : środowisko Java (na przykład Java EE lub Java SE), w którym będzie działać pakiet.
  • Moduł : Gdzie framework OSGi przetwarza modułowe aspekty pakietu. Tutaj przetwarzane są metadane pakietu.
  • Cykl życia : tutaj ma miejsce inicjowanie, uruchamianie i zatrzymywanie pakietów.
  • Rejestr usług : gdzie pakiety wymieniają swoje usługi, aby inne pakiety mogły je wykryć.

Jedną z największych wad OSGi jest brak formalnego mechanizmu instalacji pakietów natywnych.

JSR 291

JSR 291 to dynamiczny framework komponentowy dla Java SE oparty na OSGi, obecnie w końcowej fazie rozwoju. Ten wysiłek koncentruje się na przeniesieniu OSGi do głównego nurtu Java, tak jak zostało to zrobione dla mobilnego środowiska Java przez JSR 232.

JSR 294

JSR 294 definiuje system meta-modułów i deleguje rzeczywiste wykonanie podłączanych modułów (wersje, zależności, ograniczenia itp.) Zewnętrznym dostawcom. Ta specyfikacja wprowadza rozszerzenia językowe, takie jak „superpakiety” i moduły powiązane hierarchicznie, aby ułatwić modułowość. Ścisła enkapsulacja i odrębne jednostki kompilacji są również częścią zainteresowania specyfikacji. JSR 294 jest obecnie w stanie uśpienia.

Projekt Jigsaw

Projekt Jigsaw jest najbardziej prawdopodobnym kandydatem na modułowość w Javie 9. Jigsaw stara się wykorzystać konstrukcje językowe i konfiguracje środowiska do zdefiniowania skalowalnego systemu modułowego dla Java SE. Główne cele Jigsaw to:

  • Ułatwiając skalowanie środowiska wykonawczego Java SE i zestawu JDK do małych urządzeń.
  • Poprawa bezpieczeństwa Java SE i JDK poprzez zakaz dostępu do wewnętrznych interfejsów API JDK oraz wymuszanie i ulepszanie SecurityManager.checkPackageAccessmetody.
  • Poprawa wydajności aplikacji poprzez optymalizację istniejącego kodu i ułatwienie technik optymalizacji programów z wyprzedzeniem.
  • Uproszczenie tworzenia aplikacji w środowisku Java SE poprzez umożliwienie konstruowania bibliotek i aplikacji z modułów stworzonych przez programistów oraz z modułowego JDK
  • Wymaganie i egzekwowanie skończonego zestawu ograniczeń wersji

JEP (propozycja ulepszenia Java) 200

Java Enhancement Propozycja 200 utworzona w lipcu 2014 r. Ma na celu zdefiniowanie modułowej struktury JDK. JEP 200 opiera się na strukturze Jigsaw, aby ułatwić segmentację JDK, zgodnie z Java 8 Compact Profiles, na zestawy modułów, które można łączyć w czasie kompilacji, kompilacji i wdrażania. Te kombinacje modułów można następnie wdrożyć jako skalowane w dół środowiska wykonawcze, które składają się z modułów zgodnych z Jigsaw.

JEP 201

JEP 201 stara się zbudować na Jigsaw, aby zreorganizować kod źródłowy JDK na moduły. Te moduły można następnie skompilować jako odrębne jednostki za pomocą ulepszonego systemu kompilacji, który wymusza granice modułów. JEP 201 proponuje schemat restrukturyzacji kodu źródłowego w całym JDK, który kładzie nacisk na granice modułów na najwyższym poziomie drzew kodu źródłowego.

Penrose

Penrose zarządzałby interoperacyjnością między Jigsaw i OSGi. W szczególności ułatwiłoby to modyfikowanie mikro-jąder OSGi, aby pakiety działające w zmodyfikowanym jądrze mogły wykorzystywać moduły Jigsaw. Opiera się na używaniu JSON do opisu modułów.

Plany dotyczące Java 9

Java 9 to unikalna główna wersja dla języka Java. To, co czyni go wyjątkowym, to wprowadzenie modułowych komponentów i segmentów w całym JDK . Podstawowe cechy wspierające modularyzację to:

  • Modułowy kod źródłowy : w Javie 9 JRE i JDK zostaną przeorganizowane w interoperacyjne moduły. Umożliwi to tworzenie skalowalnych środowisk wykonawczych, które można uruchamiać na małych urządzeniach.
  • Segmentowana pamięć podręczna kodu : chociaż nie jest to wyłącznie funkcja modułowa, nowa segmentowana pamięć podręczna kodu Java 9 będzie zgodna z duchem modularyzacji i będzie czerpać niektóre z tych samych korzyści. Nowa pamięć podręczna kodu podejmie inteligentne decyzje dotyczące kompilacji często używanych segmentów kodu do kodu natywnego i przechowywania ich w celu zoptymalizowanego wyszukiwania i wykonywania w przyszłości. Sterta zostanie również podzielona na 3 odrębne jednostki: kod niebędący metodą, który będzie trwale przechowywany w pamięci podręcznej; kod, który ma potencjalnie długi cykl życia (znany jako „kod nieprofilowany”); i kod, który jest przejściowy (znany jako „kod profilowany”).
  • Wymuszanie czasu kompilacji: system kompilacji zostanie ulepszony za pośrednictwem JEP 201 w celu kompilowania i egzekwowania granic modułów.
  • Możliwości wdrażania : w ramach projektu Jigsaw zostaną udostępnione narzędzia, które będą obsługiwać granice modułów, ograniczenia i zależności w czasie wdrażania.

Wydanie wczesnego dostępu Java 9

Chociaż dokładna data wydania Java 9 pozostaje tajemnicą, możesz pobrać wersję wczesnego dostępu ze strony Java.net.

Podsumowując

Ten artykuł był przeglądem modułowości na platformie Java, w tym perspektyw modularności w Javie 9. Wyjaśniłem, jak długotrwałe problemy, takie jak piekło klas, przyczyniają się do potrzeby bardziej modułowej architektury Java i omówiłem niektóre z najnowszych nowych modularności funkcje proponowane dla Javy. Następnie opisałem i umieściłem w kontekście każdą z propozycji lub platform modułowości Java, w tym OSGi i Project Jigsaw.

Potrzeba bardziej modułowej architektury Java jest oczywista. Obecne próby nie powiodły się, chociaż OSGi jest bardzo blisko. W przypadku wydania Java 9, Project Jigsaw i OSGi będą głównymi graczami w modularnej przestrzeni dla Javy, a Penrose prawdopodobnie zapewni ich połączenie.

Ta historia „Modularity in Java 9: ​​Stacking up with Project Jigsaw, Penrose and OSGi” została pierwotnie opublikowana przez JavaWorld.