Dla celów argumentacji załóżmy, że Java 8 (i wcześniejsze) już je posiada „formę” modułów (jars) i systemu modułów (ścieżka klas). Ale są z nimi dobrze znane problemy.
Analizując problemy, możemy zilustrować motywację do Jigsaw. (Poniższy tekst zakłada, że nie używamy OSGi, modułów JBoss itp., Które z pewnością oferują rozwiązania.)
Problem 1: publiczny jest zbyt publiczny
Rozważ następujące klasy (załóżmy, że obie są publiczne):
com.acme.foo.db.api.UserDao
com.acme.foo.db.impl.UserDaoImpl
W Foo.com możemy zdecydować, że nasz zespół powinien użyć UserDao
a nie używaćUserDaoImpl
bezpośrednio. Jednak nie ma sposobu, aby wymusić to na ścieżce klas.
W Jigsaw moduł zawiera module-info.java
plik, który pozwala nam jawnie określić, co jest publiczne dla innych modułów. Oznacza to, że opinia publiczna ma niuanse. Na przykład:
module com.acme.foo.db {
exports com.acme.foo.db.api;
}
Problem 2: refleksja jest nieokiełznana
Biorąc pod uwagę klasy w # 1, ktoś nadal mógłby to zrobić w Javie 8:
Class c = Class.forName("com.acme.foo.db.impl.UserDaoImpl");
Object obj = c.getConstructor().newInstance();
To znaczy: refleksja jest potężna i niezbędna, ale jeśli nie jest zaznaczona, może być wykorzystana do sięgnięcia do wnętrza modułu w niepożądany sposób. Mark Reinhold podaje dość niepokojący przykład . (Post SO jest tutaj .)
W Jigsaw silna enkapsulacja daje możliwość odmowy dostępu do klasy, w tym refleksji. (Może to zależeć od ustawień wiersza poleceń, w oczekiwaniu na poprawioną specyfikację techniczną JDK 9.) Należy zauważyć, że ponieważ Jigsaw jest używany w samym JDK, Oracle twierdzi, że pozwoli to zespołowi Java na szybsze unowocześnianie wewnętrznych elementów platformy.
Problem 3: ścieżka klas wymazuje zależności architektoniczne
Zespół zazwyczaj ma model mentalny dotyczący relacji między słoikami. Na przykład foo-app.jar
może użyć, foo-services.jar
które używa foo-db.jar
. Moglibyśmy stwierdzić, że klasy w foo-app.jar
nie powinny omijać „warstwy usług” i używać ich foo-db.jar
bezpośrednio. Jednak nie ma sposobu, aby wymusić to za pomocą ścieżki klas. Mark Reinhold wspomina o tym tutaj .
Dla porównania Jigsaw oferuje wyraźny, niezawodny model dostępności dla modułów.
Problem 4: monolityczne środowisko wykonawcze
Środowisko wykonawcze Java jest monolityczne rt.jar
. Na moim komputerze jest to ponad 60 MB z 20 000 klas! W dobie mikrousług, urządzeń IoT itp. Niepożądane jest posiadanie na dysku bibliotek Corba, Swing, XML i innych, jeśli nie są używane.
Jigsaw dzieli JDK na wiele modułów; np. java.sql zawiera znane klasy SQL. Ma to kilka zalet, ale nowe jest to jlink
narzędzie. Zakładając, że aplikacja jest całkowicie zmodularyzowana, jlink
generuje dystrybuowalny obraz czasu wykonywania, który jest przycinany tak, aby zawierał tylko określone moduły (i ich zależności). Patrząc w przyszłość, Oracle przewiduje przyszłość, w której moduły JDK będą kompilowane z wyprzedzeniem do kodu natywnego. Chociaż jlink
jest to opcjonalne, a kompilacja AOT jest eksperymentalna, są one głównymi wskazówkami, dokąd zmierza Oracle.
Problem 5: wersjonowanie
Jest dobrze wiadomo, że ścieżka klasy nie pozwala nam korzystać z wielu wersji tego samego słoika: Np bar-lib-1.1.jar
i bar-lib-2.2.jar
.
Jigsaw nie rozwiązuje tego problemu; Mark Reinhold podaje tutaj uzasadnienie . Istota jest taka, że Maven, Gradle i inne narzędzia reprezentują duży ekosystem do zarządzania zależnościami, a inne rozwiązanie będzie bardziej szkodliwe niż korzystne.
Należy zauważyć, że inne rozwiązania (np. OSGi) rzeczywiście rozwiązują ten problem (i inne, oprócz punktu 4).
Podsumowanie
To kilka kluczowych punktów dla Jigsaw, motywowanych określonymi problemami.
Zwróć uwagę, że wyjaśnienie kontrowersji między Jigsaw, OSGi, JBoss Modules itp. To osobna dyskusja, która należy do innej witryny Stack Exchange. Różnic między rozwiązaniami jest znacznie więcej niż opisano tutaj. Co więcej, istniał wystarczający konsensus, aby zatwierdzić głosowanie w sprawie ponownego rozpatrzenia przeglądu publicznego dla JSR 376.