Présentation

Le Java Platform Module System (JPMS) a été introduit dans Java 9. Il vous permet d'organiser votre code en regroupant un ensemble de packages liés dans des composants de plus haut niveau appelés modules, et fournit un mécanisme pour déclarer les dépendances entre modules.


La modularisation de votre application offre plusieurs avantages :

 - Une application dont le code est organisé en modules est plus facile à lire, plus facile à maintenir et plus évolutive.

 - Les dépendances entre modules sont définies via des descripteurs de modules qui sont vérifiés à la fois à la compilation et au lancement de l'application. Cette résolution précoce des dépendances contribue à améliorer la fiabilité à l'exécution, en surmontant un problème de longue date en Java où les exceptions "NoClassDefFoundError" étaient des causes fréquentes de plantages d'application.

 - Les packages d'un module ne sont accessibles aux autres modules que s'ils sont explicitement exportés. Ce principe, appelé encapsulation forte, fournit par défaut un espace sécurisé pour le code dans lequel la réflexion ne peut pas s'immiscer.

 - Enfin, le système de modules vous permet de créer des images d'exécution personnalisées contenant uniquement les modules utilisés par votre application. La taille réduite de l'environnement d'exécution améliore notablement le temps de démarrage et l'empreinte mémoire de l'application.


À partir de la version 3.5.55, le fichier wrapper.jar contient un descripteur de module qui introduit le module 'org.tanukisoftware.wrapper'. Ce module nommé peut être inclus dans des images d'exécution personnalisées créées avec jlink.

AVERTISSEMENT

Avant la version 3.5.55, le fichier wrapper.jar n'était pas modulaire. Lorsqu'il était référencé dans le chemin de modules, un module automatique nommé 'wrapper' (dérivé du nom du fichier JAR) était créé. Ce module automatique pouvait être utilisé dans d'autres déclarations de modules, mais ne pouvait pas être utilisé par jlink pour créer des images d'exécution.

Si 'wrapper' était utilisé dans certains de vos descripteurs de modules, et que vous passez à la version 3.5.55 ou supérieure du Wrapper, n'oubliez pas de changer le nom en 'org.tanukisoftware.wrapper'.


Le Wrapper fournit plusieurs propriétés pour vous aider à configurer la façon dont les modules sont utilisés par votre application :

NOTE

Ces propriétés ne sont utilisées que lors de l'exécution avec des versions de Java 9 ou supérieure. Elles seront ignorées sur les versions antérieures.

wrapper.java.module_path.<n>

Compatibilité :3.5.55, Requires Java 9+
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

Ces propriétés sont utilisées pour lister les emplacements où les modules de votre application peuvent être trouvés. La liste peut contenir des répertoires, ou des chemins vers des fichiers jar contenant éventuellement des caractères génériques dans la partie nom de fichier.

Le Wrapper utilisera cette liste pour construire l'option '--module-path' de la ligne de commande Java.

Si un caractère générique est utilisé dans une entrée du chemin de modules, tous les fichiers correspondants seront ajoutés au chemin de modules utilisé lors du lancement d'une instance de JVM.

Les caractères génériques valides sont :

  • Un caractère '*', qui correspondra à "0" (zéro) ou plusieurs caractères.
  • Un caractère '?', qui correspondra à exactement un caractère.

Exemples de valeurs possibles pour les éléments du chemin de modules :
wrapper.java.module_path.1=../lib/myapp-*.jar  # jar files specified with a wildcard
wrapper.java.module_path.2=../lib/tools.jar    # single jar file specified using the exact name
wrapper.java.module_path.3=../lib/ext          # folder where additional modules can be found

NOTE

wrapper.jar ne doit pas être inclus dans les valeurs de cette liste de propriétés. S'il est présent, il sera retiré de la liste lors du chargement de la configuration.

Le Wrapper utilise la propriété wrapper.jarfile pour ajouter automatiquement le fichier wrapper.jar à l'endroit approprié dans la ligne de commande selon que les modules sont utilisés ou non.


Classpath :

Java n'autorise pas deux fichiers jar distincts contenant le même package à coexister dans la liste du chemin de modules. Ce n'est pas le cas avec le classpath, où le chevauchement de packages a toujours été historiquement autorisé. C'est l'une des raisons pour lesquelles le classpath reste utile, du moins jusqu'à ce qu'une application puisse être entièrement migrée vers le système de modules de Java 9.

Veuillez noter la limitation suivante : les fichiers jar listés dans le classpath qui ne peuvent être trouvés dans aucun des emplacements du chemin de modules seront utilisés par la JVM comme un module sans nom, ce qui par nature le rend inaccessible à tout autre module. Si un module est censé être référencé dans une directive requires d'un autre module, il doit exister dans l'un des emplacements spécifiés par les propriétés wrapper.java.module_path.<n> ou wrapper.java.upgrade_module_path.<n>.


Des problèmes ?

Si vous rencontrez des problèmes liés au chemin de modules, la première chose à faire est de vérifier le chemin de modules complet généré par le Wrapper. Pour ce faire, activez soit la sortie des journaux de débogage avec la propriété wrapper.debug, soit l'affichage de la commande Java à l'aide de la propriété wrapper.java.command.loglevel.

NOTE

Chemin de modules contenant des espaces :

Le Wrapper gérera correctement les éléments du chemin de modules qui contiennent des espaces. Cela est effectué ultérieurement par le Wrapper en entourant le chemin de modules final généré de visuels guillemets. Les valeurs de propriété des éléments individuels du chemin de modules ne doivent jamais être définies avec des guillemets, même si elles contiennent des espaces.

wrapper.java.module_path.missing.loglevel

Compatibilité :3.5.55, Requires Java 9+
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

Par défaut, le Wrapper journalisera des avertissements concernant tout élément manquant du Chemin de modules au niveau de journal DEBUG. Il est assez courant de vouloir voir ces messages de journal générés sans activer également toute la sortie de débogage. Cette propriété permet de spécifier le niveau de journal auquel les avertissements seront journalisés.

Les valeurs valides de la propriété comprennent :
  • FATAL :
    pour journaliser au niveau FATAL.
  • ERROR :
    pour journaliser au niveau ERROR.
  • WARN :
    pour journaliser au niveau WARN.
  • STATUS :
    pour journaliser au niveau STATUS.
  • INFO :
    pour journaliser au niveau INFO.
  • DEBUG :
    pour journaliser au niveau DEBUG.
  • NONE :
    pour ne jamais journaliser.

La valeur par défaut est DEBUG.

Exemple :
wrapper.java.module_path.missing.loglevel=DEBUG

Si votre application a souvent des jars manquants, alors définir cette valeur à NONE désactivera les avertissements à n'importe quel niveau de journal.

Les éléments du Chemin de modules définis comme des caractères génériques journaliseront également un avertissement si le caractère générique ne parvient pas à correspondre à au moins un fichier. Cela peut se produire si le répertoire est manquant ou vide.

wrapper.java.upgrade_module_path.<n>

Compatibilité :3.5.55, Requires Java 9+
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

Ces propriétés définissent une liste similaire à wrapper.java.module_path.<n>, mais permettent de remplacer les modules pouvant être mis à niveau contenus dans l'image d'exécution.

Tout comme pour wrapper.java.module_path.<n>, la liste peut contenir des répertoires, ou des chemins vers des fichiers jar contenant éventuellement des caractères génériques dans la partie nom de fichier. Pour plus de détails sur la syntaxe, veuillez vous reporter à la section ci-dessus.

Le Wrapper utilisera cette liste pour construire l'option '--upgrade-module-path' de la ligne de commande Java.

NOTE

wrapper.jar n'a pas besoin d'être inclus dans les valeurs de cette liste de propriétés.

Le Wrapper utilise la propriété wrapper.jarfile pour ajouter automatiquement le fichier wrapper.jar à l'endroit approprié dans la ligne de commande selon que les modules sont utilisés ou non.

wrapper.java.upgrade_module_path.missing.loglevel

Compatibilité :3.5.55, Requires Java 9+
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

Par défaut, le Wrapper journalisera des avertissements concernant tout élément manquant du Chemin de modules de mise à niveau au niveau de journal DEBUG. Il est assez courant de vouloir voir ces messages de journal générés sans activer également toute la sortie de débogage. Cette propriété permet de spécifier le niveau de journal auquel les avertissements seront journalisés.

Les valeurs valides de la propriété comprennent :
  • FATAL :
    pour journaliser au niveau FATAL.
  • ERROR :
    pour journaliser au niveau ERROR.
  • WARN :
    pour journaliser au niveau WARN.
  • STATUS :
    pour journaliser au niveau STATUS.
  • INFO :
    pour journaliser au niveau INFO.
  • DEBUG :
    pour journaliser au niveau DEBUG.
  • NONE :
    pour ne jamais journaliser.

La valeur par défaut est DEBUG.

Exemple :
wrapper.java.upgrade_module_path.missing.loglevel=DEBUG

Si votre application a souvent des jars manquants, alors définir cette valeur à NONE désactivera les avertissements à n'importe quel niveau de journal.

Les éléments du Chemin de modules de mise à niveau définis comme des caractères génériques journaliseront également un avertissement si le caractère générique ne parvient pas à correspondre à au moins un fichier. Cela peut se produire si le répertoire est manquant ou vide.

wrapper.java.module.<n>

Compatibilité :3.5.55, Requires Java 9+
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

Ces propriétés sont utilisées pour lister les noms des modules racine utilisés par votre application. Les modules racine sont des modules qui ne peuvent pas être intégrés au graphe de modules lors du lancement de l'application, soit parce qu'ils ne sont requis par aucun autre module, soit parce qu'ils sont des dépendances optionnelles (c.-à-d. spécifiées avec 'requires static' dans un descripteur de module).

Le Wrapper utilisera cette liste pour construire l'option '--add-modules' de la ligne de commande Java.

En plus des noms de modules, la liste peut inclure les jetons suivants :

Veuillez consulter la spécification OpenJDK pour une description plus détaillée.

wrapper.java.module.<n>.enable_native_access

Compatibilité :3.6.1, Requires Java 24+
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

À partir du JDK 24, dans le cadre d'une politique d'intégrité par défaut, l'accès au code natif via JNI ou FFM est soumis à des restrictions. Des opérations telles que System::loadLibrary (JNI), Linker::downcallHandle (FFM) déclencheront des avertissements ou lèveront potentiellement des exceptions à moins d'avoir reçu une approbation explicite du développeur de l'application.

Exemple d'avertissement affiché avec Java 24 :
jvm 1    | WARNING: A restricted method in java.lang.System has been called
jvm 1    | WARNING: java.lang.System::loadLibrary has been called by com.foo.Server in module com.foo (file:/path/to/com.foo.jar)
jvm 1    | WARNING: Use --enable-native-access=com.foo to avoid a warning for callers in this module
jvm 1    | WARNING: Restricted methods will be blocked in a future release unless native access is enabled

Les propriétés wrapper.java.module.<n>.enable_native_access permettent d'activer l'accès natif pour des modules spécifiques. Ces propriétés sont ignorées lors de l'exécution sur des versions de Java antérieures à 24.

La valeur par défaut est "FALSE" afin de suivre le principe d'intégrité par défaut.

Autoriser 'com.foo' à accéder au code natif :
wrapper.java.module.1=com.foo
wrapper.java.module.1.enable_native_access=TRUE

NOTE

Le Wrapper s'appuie sur du code natif pour que plusieurs fonctionnalités importantes fonctionnent correctement. Pour cette raison, le module 'org.tanukisoftware.com' se verra automatiquement accorder l'accès au code natif, et ce paramètre ne peut pas être modifié.

Lorsque des fichiers jar sont référencés dans le classpath, ils appartiennent à un module par défaut connu sous le nom de module ALL-UNNAMED. Il est également possible d'autoriser ce module à accéder au code natif. Cependant, pour une meilleure sécurité, nous recommandons d'adopter une approche plus granulaire où votre application est structurée en modules distincts, et de n'accorder l'accès au code natif qu'aux modules qui en ont réellement besoin.

Autoriser 'ALL-UNNAMED' à accéder au code natif :
wrapper.java.module.1=ALL-UNNAMED
wrapper.java.module.1.enable_native_access=TRUE

Veuillez consulter la page JDK 24: Prepares Restricted Native Access pour une description plus détaillée.