Le système de gestion des packages de Java m'a toujours semblé simple et efficace. Il est largement utilisé par le JDK lui-même. Nous l'avons utilisé pour imiter le concept d'espaces de noms et de modules.
Qu'est-ce que Jigsaw Project (aka Java Platform Module System ) essaie de remplir?
Depuis le site officiel:
Le but de ce projet est de concevoir et de mettre en œuvre un système de modules standard pour la plate-forme Java SE) et d'appliquer ce système à la plate-forme elle-même et au JDK.
Jigsaw et OSGi tentent de résoudre le même problème: comment permettre aux modules plus grossiers d'interagir tout en protégeant leurs composants internes.
Dans le cas de Jigsaw, les modules à granularité plus grossière incluent Java classes, packages et leurs dépendances).
Voici un exemple: Spring et Hibernate. Les deux ont une dépendance sur un JAR CGLIB tiers, mais ils utilisent des versions différentes et incompatibles de ce JAR. Que pouvez-vous faire si vous comptez sur le JDK standard? Y compris la version que Spring veut casser Hibernate et vice versa.
Mais, si vous avez un modèle de niveau supérieur comme Jigsaw, vous pouvez facilement gérer différentes versions d'un JAR dans différents modules. Considérez-les comme des packages de niveau supérieur.
Si vous construisez Spring à partir de la source GitHub vous le verrez aussi. Ils ont refait le cadre de sorte qu'il se compose de plusieurs modules: noyau, persistance, etc. Vous pouvez choisir et choisir l'ensemble minimal de dépendances de module dont votre application a besoin et ignorer le reste. Auparavant, il s'agissait d'un seul fichier Spring JAR contenant tous les fichiers .class.
Mise à jour: cinq ans plus tard - Jigsaw pourrait encore avoir problèmes à résoudre.
AFAIK L'objectif est de rendre le JRE plus modulaire. C'est à dire. ont des pots plus petits qui sont facultatifs et/ou vous pouvez télécharger/mettre à niveau uniquement les fonctionnalités dont vous avez besoin.
C'est pour le rendre moins gonflé et vous donner la possibilité de supprimer les modules hérités que la plupart des gens n'utilisent peut-être pas.
Basé sur Mark Reinholddiscours d'ouverture à Devoxx Belgique , Project Jigsaw va aborder deux points principaux:
Nous connaissons tous le JAR Hell . Ce terme décrit toutes les différentes manières dont le processus classloading peut finir par ne pas fonctionner. Les limitations les plus connues de classpath sont:
La grande nature monolithique de JDK pose plusieurs problèmes:
Pour résoudre les problèmes ci-dessus, nous traitons les modules comme un nouveau type fondamental de composant de programme Java. Un module est une collection nommée et auto-descriptive de code et de données. Son code est organisé comme un ensemble de packages contenant des types, c'est-à-dire Java classes et interfaces; ses données incluent des ressources et d'autres types d'informations statiques.
Pour contrôler la façon dont son code fait référence aux types dans d'autres modules, un module déclare les autres modules dont il a besoin pour être compilé et exécuté. Pour contrôler la façon dont le code des autres modules fait référence aux types dans ses packages, un module déclare lequel de ces packages il exporte.
Le système de modules localise les modules requis et, contrairement au mécanisme de chemin de classe, garantit que le code dans un module ne peut se référer qu'aux types des modules dont il dépend. Les mécanismes de contrôle d'accès du langage Java et de la machine virtuelle Java) empêchent le code d'accéder aux types dans les packages qui ne sont pas exportés par leurs modules de définition.
En plus d'être plus fiable, la modularité pourrait améliorer les performances. Lorsque le code dans un module fait référence à un type dans un package, ce package est garanti d'être défini soit dans ce module, soit précisément dans l'un des modules lus par ce module. Lors de la recherche de la définition d'un type spécifique, il n'est donc pas nécessaire de la rechercher dans plusieurs modules ou, pire, tout au long du chemin de classe.
Jigsaw est un énorme projet qui se poursuit depuis plusieurs années. Il a une quantité impressionnante de JEP qui sont d'excellents endroits pour obtenir plus d'informations sur le projet. Certains de ces JEP sont les suivants:
Dans l'édition initiale du rapport L'état du système de modules , Mark Reinhold décrit les objectifs spécifiques du système de modules comme suit:
Ces fonctionnalités profiteront aux développeurs d'applications, aux développeurs de bibliothèques et aux implémenteurs de la plate-forme Java SE elle-même directement et indirectement, car elles permettront une plate-forme évolutive, une plus grande intégrité de la plate-forme et des performances améliorées.
Pour les besoins de l'argument, affirmons que Java 8 (et versions antérieures) a déjà une "forme" de modules (jars) et de système de modules (le chemin de classe ). Mais ces problèmes sont bien connus.
En examinant les problèmes, nous pouvons illustrer la motivation de Jigsaw. (Ce qui suit suppose que nous n'utilisons pas les modules OSGi, JBoss, etc., qui offrent certainement des solutions.)
Problème 1: public est aussi public
Considérez les classes suivantes (supposez que les deux sont publiques):
com.acme.foo.db.api.UserDao
com.acme.foo.db.impl.UserDaoImpl
Chez Foo.com, nous pourrions décider que notre équipe devrait utiliser UserDao
et non pas UserDaoImpl
directement. Cependant, il n'y a aucun moyen d'imposer cela sur le chemin de classe.
Dans Jigsaw, un module contient un module-info.Java
fichier qui nous permet de déclarer explicitement ce qui est public pour les autres modules. Autrement dit, le public a des nuances. Par exemple:
// com.acme.foo.db.api.UserDao is accessible, but
// com.acme.foo.db.impl.UserDaoImpl is not
module com.acme.foo.db {
exports com.acme.foo.db.api;
}
Problème 2: la réflexion est débridée
Étant donné les classes de # 1, quelqu'un pourrait toujours le faire en Java 8:
Class c = Class.forName("com.acme.foo.db.impl.UserDaoImpl");
Object obj = c.getConstructor().newInstance();
C'est-à-dire que la réflexion est puissante et essentielle, mais si elle n'est pas cochée, elle peut être utilisée pour pénétrer dans les internes d'un module de manière indésirable. Mark Reinhold a plutôt un exemple alarmant . (Le message SO est ici .)
Dans Jigsaw, encapsulation forte offre la possibilité de refuser l'accès à une classe, y compris la réflexion. (Cela peut dépendre des paramètres de ligne de commande, dans l'attente de la spécification technique révisée pour JDK 9.) Notez que parce que Jigsaw est utilisé pour le JDK lui-même, Oracle prétend que cela permettra à l'équipe Java innover plus rapidement les plateformes internes.
Problème 3: le chemin de classe efface les relations architecturales
Une équipe a généralement un modèle mental sur les relations entre les pots. Par exemple, foo-app.jar
peut utiliser foo-services.jar
qui utilise foo-db.jar
. On pourrait affirmer que les classes dans foo-app.jar
ne doit pas contourner "la couche de service" et utiliser foo-db.jar
directement. Cependant, il n'y a aucun moyen de l'imposer via le chemin de classe. Mark Reinhold mentionne ceci ici .
En comparaison, Jigsaw propose un modèle d'accessibilité explicite et fiable pour les modules.
Problème 4: exécution monolithique
Le Java runtime est dans le monolithique rt.jar
. Sur ma machine, c'est 60+ MB avec 20k classes! À l'ère des micro-services, des appareils IoT, etc., il n'est pas souhaitable d'avoir Corba, Swing, XML et d'autres bibliothèques sur disque si elles ne sont pas utilisées.
Jigsaw décompose le JDK lui-même en plusieurs modules; par exemple. Java.sql contient les classes SQL familières. Il y a plusieurs avantages à cela, mais un nouveau est l'outil jlink
. En supposant qu'une application est complètement modularisée, jlink
génère un image d'exécution distribuable qui est coupé pour contenir uniquement les modules spécifiés (et leurs dépendances). Pour l'avenir, Oracle envisage un avenir où les modules JDK sont compilés à l'avance en code natif. Bien que jlink
soit facultatif et que la compilation AOT soit expérimentale, ce sont des indications majeures de l'orientation d'Oracle.
Problème 5: versioning
Il est bien connu que le chemin de classe ne nous permet pas d'utiliser plusieurs versions du même pot: par ex. bar-lib-1.1.jar
et bar-lib-2.2.jar
.
Jigsaw ne résout pas ce problème; Mark Reinhold déclare le justification ici . L'essentiel est que Maven, Gradle et d'autres outils représentent un vaste écosystème pour la gestion des dépendances, et une autre solution sera plus nuisible que bénéfique.
Il convient de noter que d'autres solutions (par exemple OSGi) résolvent effectivement ce problème (et d'autres, à part le n ° 4).
Conclusion
Voilà quelques points clés pour Jigsaw, motivés par des problèmes spécifiques.
Notez que l'explication de la controverse entre Jigsaw, OSGi, JBoss Modules, etc. est une discussion distincte qui appartient à un autre site Stack Exchange. Il existe beaucoup plus de différences entre les solutions que celles décrites ici. De plus, il y avait un consensus suffisant pour approuver le scrutin de réexamen public pour JSR 376.
Cet article explique en détail les problèmes que OSGi et JPMS/Jigsaw tentent de résoudre:
"Java 9, OSGi et l'avenir de la modularité" [22 SEP 2016]
Il va également à fond dans les approches d'OSGi et de JPMS/Jigsaw. À l'heure actuelle, il semble que les auteurs n'aient répertorié pratiquement aucun avantage pratique pour JPMS/Jigsaw par rapport à l'OSGi mature (16 ans).