Fichiers de log – Utilité et mise en oeuvre

La production de fichiers de log avec un contenu de qualité doit être considéré avec une grande attention lors de la réalisation des applications logicielles. L’objectif de cette production est d’améliorer les conditions d’exploitation de ces applications, notamment en cas de problème.

Plusieurs outils logiciels existent pour rendre plus simple et plus efficace l’integration de cette fonctionnalité. Cet article présente ces outils et leur utilisation concrète. La présentation est guidée par l’objectif annoncé et introduit les articles suivants qui détailleront la mise en oeuvre de façon pratique.

Ce tutoriel fait partie d’une série de cinq articles qui permettront de clarifier l’importance et la manière d’intégrer cette fonctionnalité dans une application logicielle:

  1. Cet article: Fichiers de log – Utilité et mise en oeuvre
  2. A venir: Fichiers de log en Java
  3. A venir: Fichiers de log en code natif
  4. A venir: Centraliser les logs des applications réparties
  5. A venir: Analyser et exploiter efficacement le contenu des logs

1. Utilité des fichiers de log

En production, une application logicielle  fonctionne hors de portée des outils de développement qui ont servi à la construire. Notamment elle est hors de portée des debuggers qui permettent de localiser rapidement une erreur. Cela réduit considérablement les possibilités d’investigation en cas de problème. La présence de logs produits par cette application contribue à étendre le champ d’investigation et donc à améliorer les possibilités de diagnostiquer les problèmes. C’est la principale utilité des fichiers de log.

En plus des informations fournies sur les anomalies d’exécution, ces fichiers peuvent servir à mieux supériviser le fonctionnement moyennant un système tel que Nagios. Ils peuvent, également, aider à prévenir certains types d’anomalies tel que la surcharge excessive y compris celle provoquée par attaque de deni de service (DoS).

2. Considérations de mise en oeuvre

La mise en oeuvre de le production de fichiers de log dans une application logicielle doit prendre en compte certaines considérations:

  • Minimiser au maximum les ressources utilisées: La production de ces fichiers a forcément un coût. Cette minimisation permet d’éviter tout mpact sur les preformances des traitements de l’application.
  • Simplicité de mise en place: Afin de ne pas se détourner du coeur de l’application.
  • Bien penser le contenu: La qualité de l’information contenue par les logs est essentielle pour atteindre les objectifs visés. Cette exigence de qualité concerne le contenu de l’information elle même. Elle concerne aussi l’emplacement, dans le code, où on génère cette information, c’est à dire l’évenement applicatif qui provoque cette génération.

Des librairies, des frameworks et des plugins systèmes existent. Ces composants logiciels prennent en compte ces considérations. L’integration d’une fonctionnalité de production de fichiers de logs doit, en principe, utiliser ces outils existants.

Share

Modules Java: Une application exemple – Intérêts

Ce tutoriel sur les modules Java traite la réalisation finale de l’application exemple. Il présente quelques aspects de l’intérêt de l’architecture modulaire utilisée pour la construire .

Ce tutoriel fait partie d’une série de quatre articles qui permettront de cerner ce nouveau concept afin de l’utiliser pour plus de robustesse et de maintenabilité des applications développées en Java:

  1. Modules Java: Présentation et concepts
  2. Modules Java: JRE modulaire
  3. Modules Java: Une application exemple – Conception
  4. Cet article: Modules Java: Une application exemple – Intérêts

1. Réalisation finale de l’application exemple

Pour finaliser la réalisation de l’application présentée comme exemple d’utilisation des modules Java, on va créer le module principal net.mtuto.superprocess. Ce module contient le point d’entrée de l’application.

Se positionner dans le dossier de travail application/. Créer, ensuite, la classe unique de ce module:

mkdir src/net/mtuto/superprocess/
vi src/net/mtuto/superprocess/SProcesseur.java

Contenu de ce fichier:

package net.mtuto.superprocess;
import java.util.*;
import net.mtuto.repartition.facade.Repartiteur;
public class SProcesseur  
{
    public static void main( String[] args )
    {
        System.out.print("Super processeur, que voulez-vous traiter ?: ");
        Scanner scanner = new Scanner(System.in);
        String sujet = scanner.nextLine();
        Repartiteur r = new Repartiteur();
        List<String> lr = r.traiter(sujet);
        for (String s: lr) System.out.println(s);
    }
}

Créer le descripteur de ce module principal dans src/module-info.java:

module net.mtuto.superprocess {
  exports net.mtuto.superprocess;
  requires net.mtuto.repartition;
}

Enfin, compiler et créer le fichier JAR du module:

javac --add-modules net.mtuto.repartition -p spmodules/ -d classes src/module-info.java src/net/mtuto/superprocess/SProcesseur.java
jar --create --file spmodules/superprocess.jar --main-class net.mtuto.superprocess.SProcesseur -C classes/ .

2. Essais d’exécution

A ce stade, la réalisation de l’application est achevée. L’ensemble des éléments de l’application est sous forme de modules Java. Ces modules sont contenus dans des fichiers JAR qui se trouvent dans le dossier application/spmodules. Exécuter:

ls -l spmodules/*.jar

Le résultat doit être:

modules java exemplePour exécuter l’application:

java --module-path spmodules/ -m net.mtuto.superprocess

Essayer plusieurs exécutions, avec à chaque fois un objet différent du traitement: 1234, 1234 + 5678, 1234 x 5678, finir et enfin: marcher. Remarquer que l’application répond bien au cahier des charges de départ.

3. Vérification préalable de la cohérence des modules

L’un des apports importants des modules Java est la vérification préalable à l’exécution de la cohérence des modules constituant une application. En Java 1.8-, cette vérificartion est inexistante et la JVM charge les classes exécutées au fur et à mesure de l’avancement de l’exécution et en se fiant à l’ordre définit dans le classpath. De ce fait, ce n’est qu’au cours de l’exécution que la JVM peut se rendre compte de l’absence (ou l’incohérence) d’une partie du code exécutable.

Supprimons un module du dossier qui les contient et tentons de lancer l’application. Exécuter dans l’ordre:

mkdir tmp
mv spmodules/calcul.jar tmp/ 
java --module-path spmodules/ -m net.mtuto.superprocess

L’application ne s’exécute pas et on obtient un message d’erreur dès le lancement:

Error occurred during initialization of boot layer
java.lang.module.FindException: Module net.mtuto.calcul not found, required by net.mtuto.repartition

Ce message est très claire: il manque le module net.mtuto.calcul à l’arbre de dépendance de l’application. Exécuter maintenant:

cp -p tmp/calcul.jar spmodules/
mv tmp/calcul.jar spmodules/calcul2.jar

Le module net.mtuto.calcul est, maintenant, dupliqué. L’application ne s’exécute pas et on obtient un message d’erreur au lancement:

Error occurred during initialization of boot layer                                                                                                                                           
java.lang.module.FindException: Two versions of module net.mtuto.calcul found in spmodules (calcul.jar and calcul2.jar)

Fini le risque d’utilisation de plusieurs versions des mêmes librairies, les conflits de versions et le JAR Hell (enfin je ne suis pas tout à fait certain de ce dernier point car il est trop tôt pour en être certain mais on l’espère bien).

Supprimer le fichier calcul2.jar pour pouvoir poursuivre dans de bonnes conditions.

4. Evolution fonctionnelle facilitée

On se propose de faire évoluer le fonctionnement de l’application de manière à rendre le résultat de calcul plus lisible. La réponse doit comporter l’opération demandée = résultat au lieu du résultat seul.

Au regard de l’architecture modulaire de l’application, seul le module net.mtuto.calcul doit être modifié. De plus seule la classe de façade Calculer.java doit l’être. Tout le risque de la modification se trouve donc confiné à cette partie du code applicatif. Modifier cette classe de manière que deux lignes des méthodes addition et multiplication deviennent:

...
return opAddition + " = " + addition.additionner(a,b).toString();
...
return opMultiplication + " = " + multiplication.multiplier(a,b).toString();
...

Après cela, on reconstruit le module calcul seulement.

cd spmodules/calcul
javac -d classes src/*.java src/net/mtuto/calcul/facade/*.java src/net/mtuto/calcul/traitement/*.java
jar --create -M --file ../calcul.jar -C classes/ .

La partie modifiée étant bien encapsulée et isolée du reste du code, on peut sans prendre de risque, ne tester que cette partie modifiée. Souvent un test unitaire automatisé suffit.

5. Réalisation plus rapide

Avec une architecture modulaire, les modules Java constituent des unités applicatives avec un couplage faible entre elles. Ceci favorise la réalisation de ces unités par des équipes différentes travaillant en parallèle. Cette architecture favorise également les tests unitaires automatisés du code réalisé.

Share

Modules Java: Une application exemple – Conception

Cet article traite le sujet de l’utilisation concrète des modules Java. Il présente la premère partie de la construction progressive d’une application écrite en Java 9+. Cette application est modulaire dans la mesure où elle est construite par assemblage de modules au sens de Java 9+. L’objectif étant de montrer la manière de construire ce type d’applications.

Ce tutoriel fait partie d’une série de quatre articles qui permettront de cerner ce nouveau concept afin de l’utiliser pour plus de robustesse et de maintenabilité des applications développées en Java:

  1. Modules Java: Présentation et concepts
  2. Modules Java: JRE modulaire
  3. Cet article: Modules Java: Une application exemple – Conception
  4. Modules Java: Une application exemple – Intérêts

1. Fonctionnement de l’application

Cette application exemple doit demander une entrée au format texte, la traiter et restituer un résultat.
Elle est capable d’effectuer les traitements:

  1. Addition de deux entiers.
  2. Multiplication de deux entiers.
  3. Conjuguaison d’un verbe du 1er groupe au présent de l’indicatif.

2. Conception de l’application

En vertu du principe de la séparation des traitements et de la présentation il y aura une partie présentation et une autre de traitement. La partie présentation est simple dans notre cas, elle ne sera constituée que par un seul module. Toutefois, la partie traitement comporte deux types de traitements:

  1. Le calcul, qui sera constitué par un module.
  2. La conjugaison, qui sera constitué par un autre module.

Cela fait trois modules différents. D’un autre côté, l’entrée étant en format texte brut, il nous faudra un quatrème module qui s’occupera de décortiquer cette entrée et faire la répartition des tâches en conséquence. En fin de compte, on doit avoir les modules suivants:

  1. Module principal qui prend en charge l’interface utilisateur: net.mtuto.superprocess
  2. Module de répartition: net.mtuto.repartition
  3. Module de calcul: net.mtuto.clacul
  4. Module de conjugaison: net.mtuto.conjugaison

Arbre de dépendance de l’application: en couleur verte les dépendances internes, en couleur rouge les dépendances au JRE.

Le module principal superprocess n’aura aucun lien avec les modules de traitement et aucune connaissance de leur existence. Ce module ne dépend que du module repartition. Le module repartition, de son côté, dépend des 2 modules de traitement. Enfin, les deux modules de traitement sont totalement indépendants l’un de l’autre.

3. Le module conjugaison

Ce module sera composé de deux packages:

  • net.mtuto.conjugaison.facade: joue le rôle d’interface et contient une classe unique Conjuguer
  • net.mtuto.conjugaison.traitement: contient les détails des traitements, effectués par la classe Groupe1

Pour créer ce module, exécuter:

mkdir -p application/spmodules/conjugaison/src/net/mtuto/conjugaison/facade
mkdir -p application/spmodules/conjugaison/src/net/mtuto/conjugaison/traitement
cd application/spmodules/conjugaison
vi src/net/mtuto/conjugaison/facade/Conjuguer.java

Saisir dans l’éditeur de texte le contenu de ce fichier de classe:

package net.mtuto.conjugaison.facade;
import java.util.*;
import net.mtuto.conjugaison.traitement.Groupe1;
public class Conjuguer {
  public List<String> groupe1pind(String verbe) {
    Groupe1 g1 = new Groupe1();
    return g1.presentind(verbe);
  }
}

Suite à cela, enregistrer et quitter, ensuite créer de la même manière la classe de traitement:

vi src/net/mtuto/conjugaison/traitement/Groupe1.java

Saisir dans l’éditeur de texte le contenu de ce fichier de classe:

package net.mtuto.conjugaison.traitement;
import java.util.*;
public class Groupe1 {
  public List<String> presentind(String verbe) {
    String racine = verbe.substring(0, verbe.length() - 2);
    List<String> r = new ArrayList<String>();
    r.add("Je " + racine + "e");
    r.add("Tu " + racine + "es");
    r.add("Il " + racine + "e");
    r.add("Nous " + racine + "ons");
    r.add("Vous " + racine + "ez");
    r.add("Ils " + racine + "ent");
    return r;
  }
}

Après l’enregistrement de ce fichier de classe, on crée le descripteur du module:

vi src/module-info.java

Le contenu de ce fichier doit être:

module net.mtuto.conjugaison {
  exports net.mtuto.conjugaison.facade;
}

Après avoir fini avec la création de ces trois fichiers sources, on peut construire le module dans application/spmodules/conjugaison.jar:

mkdir classes
javac -d classes src/module-info.java src/net/mtuto/conjugaison/facade/Conjuguer.java src/net/mtuto/conjugaison/traitement/Groupe1.java
jar --create -M --file ../conjugaison.jar -C classes/ .

4. Le module calcul

Ce module sera composé, en plus du descripteur, par 3 classes:

  1. net.mtuto.calcul.facade.Calculer
  2. net.mtuto.calcul.traitement.Addition
  3. net.mtuto.calcul.traitement.Multiplication

Pour créer ce module, il convient de procéder comme pour le module conjugaison: créer les dossiers puis les fichiers de chacun de ces éléments. Les contenus doivent être:

Calculer.java:

package net.mtuto.calcul.facade;
import net.mtuto.calcul.traitement.Addition;
import net.mtuto.calcul.traitement.Multiplication;
public class Calculer {
  public String addition(String opAddition) {
    Addition addition = new Addition();
    String[] parties = opAddition.split(" ");
    int a = Integer.parseInt(parties[0]);
    int b = Integer.parseInt(parties[2]);
    return addition.additionner(a,b).toString();
  }
  public String multiplication(String opMultiplication) {
    Multiplication multiplication = new Multiplication();
    String[] parties = opMultiplication.split(" ");
    int a = Integer.parseInt(parties[0]);
    int b = Integer.parseInt(parties[2]);
    return multiplication.multiplier(a,b).toString();
  }
}

Addition.java:

package net.mtuto.calcul.traitement;
public class Addition {
  public Integer additionner(int a, int b) {
    return a + b;
  }
}

Multiplication.java:

package net.mtuto.calcul.traitement;
public class Multiplication {
  public Integer multiplier(int a, int b) {
    return a * b;
  }
}

module-info.java:

module net.mtuto.calcul {
 exports net.mtuto.calcul.facade;
}

Une fois ces quatre fichiers sources crées, on peut construire le module dans application/spmodules/calcul.jar:

mkdir classes
javac -d classes src/*.java src/net/mtuto/calcul/facade/*.java src/net/mtuto/calcul/traitement/*.java
jar --create -M --file ../calcul.jar -C classes/ .

5. Le module repartition

Ce module sera composé par le descripteur et une seule classe: net.mtuto.repartition.facade.Repartiteur

Pour le créer, il convient de procéder comme pour le module conjugaison: créer les dossiers puis les fichiers de chacun de ces éléments. Les contenus doivent être:

Repartiteur.java:

package net.mtuto.repartition.facade;
import java.util.*;
import net.mtuto.conjugaison.facade.Conjuguer;
import net.mtuto.calcul.facade.Calculer;
public class Repartiteur {
  public List traiter(String txt) {
    List r = new ArrayList();
    String[] parties = txt.trim().split(" ");
    if (parties.length == 1) {
      if (parties[0].length()>2 && parties[0].toLowerCase().substring(parties[0].length()-2, parties[0].length()).equals("er")) {
        Conjuguer c = new Conjuguer();
        r = c.groupe1pind(txt);
      } else r.add("Impossible de traiter les données fournies");
    } else if (parties.length == 3) {
      int a = -1;
      int b = -1;
      try {
        a = Integer.parseInt(parties[0]);
        b = Integer.parseInt(parties[2]);
      } catch (NumberFormatException nfe) {
        a = -1;
        b = -1;
        r.add("Impossible de traiter les données fournies: l'un des arguments numériques est faux ou négatif");
      }
      if (a>=0 && b>=0 && (parties[1].equals("+") || parties[1].equals("x"))) {
        Calculer c = new Calculer();
        if (parties[1].equals("x")) r.add(c.multiplication(txt));
        else r.add(c.addition(txt));
      } else r.add("Impossible de traiter les données fournies");
    } else r.add("Impossible de traiter les données fournies");
    return r;
  }
}

module-info.java:

module net.mtuto.repartition {
  exports net.mtuto.repartition.facade;
  requires net.mtuto.calcul;
  requires net.mtuto.conjugaison;
}

Après la création de ces deux fichiers sources, on procède à la construction du module dans application/spmodules/repartition.jar:

mkdir classes/
javac --add-modules net.mtuto.conjugaison,net.mtuto.calcul -p ../ -d classes src/module-info.java src/net/mtuto/repartition/facade/Repartiteur.java
jar --create -M --file ../repartition.jar -C classes/ .
Share

Modules Java: JRE modulaire

En introduisant la notion de module, en toute logique, Java s’est modularisé lui-même également. A partir de la version 9, donc, l’environnement d’exécution (JRE) mais aussi l’environnement de développement (JDK), ont subi une refonte en profondeur. Le but de cette refonte est de rendre modulaire la structure du système. Ce tutoriel a pour objectif de montrer les principaux impacts de cette évolution mais également faire le lien avec la (nouvelle) manière d’utiliser Java, dont la possibilité de construire un JRE personnalisé.

Ce tutoriel fait partie d’une série de trois articles qui permettront de cerner ce nouveau concept afin de l’utiliser pour plus de robustesse et maintenabilité des applications développées en Java:

  1. Modules Java: Présentation et concepts
  2. Cet article: Modules Java: JRE modulaire
  3. Modules Java: Une application exemple – Conception
  4. Modules Java: Une application exemple – Intérêts

1. Une structure plus simple et plus efficace du système.

La meilleur façon d’appréhender cette évolution de la structure est de faire une comparaison de l’existant antérieurement (version 1.8-) avec la nouvelle structure. Pour effectuer cette comparaison, on doit disposer de deux versions de Java sur le système. Une 1.8- et une 9+.

Exécuter les deux commandes, observer les résultats et comparer (adapter, si besoin, les numéros de version dans les chemins cibles aux versions installées):

tree -d -I legal\|man\|docs /usr/lib/jvm/java-1.8.0-openjdk-amd64/
tree -d -I legal\|man\|docs /usr/lib/jvm/java-9-openjdk-amd64/

La commande tree n’est pas installée systématiquement sur le système utilisé. Si c’est le cas, installez la avec la commande: sudo apt install tree. Dans ces deux commandes on n’affiche que les dossiers et on exclu les dossiers: legal/, man/ et docs/ qui ne contiennent que de la documentation et sont hors d’intérêt pour cet exposé.

Modules Java

A gauche l’ancienne arborescence Java 1.8-, à droite la nouvelle de Java 9+. On peut constater dès le départ une nette simplification et une meilleur organisation de la structure des dossiers.

Dans le détail:

  • L’apparition de deux nouveaus dossiers: conf/ destiné à contenir les fichiers de configuration et jmods/ destiné à contenir les fichiers des modules java du système, JRE et JDK.
  • Le déplacement de la partie configuration du JRE dans le dossier conf/
  • La disparition du dossier de la JRE.
  • Un seul dossier bin/ et un seul dossier lib/ destinés à acueillir respectivement les fichiers exécutables et les librairies essentiellement natives du JRE et du JDK.

2. Une utilisation plus simple de Java 9+

Si on considère que Java est installé dans le dossier JAVA_INSTALLATION/ (donc /usr/lib/jvm/java-9-openjdk-amd64/ pour un système Ubuntu/Debian):

  • Toutes les commandes exécutables du JRE et du JDK sont dans : JAVA_INSTALLATION/bin. Il suffit donc d’ajouter ce chemin à la configuration du système (chemin PATH).
  • Toutes les librairies natives du système sont dans JAVA_INSTALLATION/lib. Si besoin, il suffit d’indiquer ce chemin au système pour ce type de librairie.
  • Tous les modules (librairies Java du système) sont dans JAVA_INSTALLATION/jmods, il suffit donc d’utiliser ce chemin pour le paramètre –module-path de Java 9+.

Maintenant, vérifions les contenus de ces trois dossiers importants. Adaptez, dans cette commande,  le numéro de version de Java dans le chemin cible. Cette version pourrait être  10 ou 11 (Novembre 2018):

ls -l /usr/lib/jvm/java-9-openjdk-amd64/bin

Le résultat partiel de cette commande est:

-rwxr-xr-x 1 root root  10424 oct.   7 17:06 jaotc
-rwxr-xr-x 1 root root  10368 oct.   7 17:06 jar
-rwxr-xr-x 1 root root  10376 oct.   7 17:06 jarsigner
-rwxr-xr-x 1 root root  10344 oct.   7 17:06 java
-rwxr-xr-x 1 root root  10400 oct.   7 17:06 javac
-rwxr-xr-x 1 root root  10408 oct.   7 17:06 javadoc
-rwxr-xr-x 1 root root  10400 oct.   7 17:06 jlink
-rwxr-xr-x 1 root root  10368 oct.   7 17:06 jmod

On remarque la présence des exécutables java (JRE), javac (JDK), jlink (JDK)..

ls -l /usr/lib/jvm/java-9-openjdk-amd64/lib

Le résultat partiel de cette commande est:

-rw-r--r-- 1 root root     22976 oct.   7 17:06 libjimage.so
-rw-r--r-- 1 root root     96960 oct.   7 17:06 libnet.so
-rw-r--r-- 1 root root     72672 oct.   7 17:06 libnio.so
-rw-r--r-- 1 root root     10288 oct.   7 17:06 libprefs.so
-rw-r--r-- 1 root root      6128 oct.   7 17:06 librmi.so

On remarque la présence des librairies dynamiques partagées natives libnet.so, libnio.so, librmi.so ..

ls -l /usr/lib/jvm/java-9-openjdk-amd64/jmods

Le résultat partiel de cette commande est:

-rw-r--r-- 1 root root 19040174 oct.   7 17:06 java.base.jmod
-rw-r--r-- 1 root root   128362 oct.   7 17:06 java.logging.jmod
-rw-r--r-- 1 root root   381849 oct.   7 17:06 java.rmi.jmod
-rw-r--r-- 1 root root  6503544 oct.   7 17:06 jdk.compiler.jmod
-rw-r--r-- 1 root root   245838 oct.   7 17:06 jdk.jartool.jmod
-rw-r--r-- 1 root root   630021 oct.   7 17:06 jdk.jshell.jmod

On remarque la présence des modules java.base (JRE), java.logging (JRE), jdk.jartool (JDK)..

3. Le nouveau format de paquet JMOD

A l’exploration du contenu du dossier jmods/, on remarque que les fichiers des modules JRE et JDK ont l’extension .jmod. Il s’agit d’un nouveau format introduit par la version 9 et qui comporte des capacités plus évoluées que celles du format JAR. Le format JMOD permet d’embarquer dans un même fichier les bytecode java compilés (.class) avec des fichiers statiques, qui peuvent servir à la configuration par exemple, ainsi que du code natif. Toutefois, les fichiers ainsi créés sont destinés seulement pour des environnements de développement.

L’utilitaire jmod, fichier exécutable dans le dossier bin/, permet de gérer ce type de fichier. Notament, le paramètre create permet la création de ces paquets. Pour plus de détails à propos de son fonctionnement exécuter:

jmod --help

Enfin, la connaissance de la liste des modules disponibles pour le système installé ne passe pas forcément par l’exploration du dossier jmods/. On peut afficher cette liste avec la commande:

java --list-modules

4. Création d’une image exécutable personnalisée

Le principe de fonctionnement de Java repose sur le code intermédiaire (bytecode) et l’environnement d’exécution (JRE). Ce principe permet d’exécuter le même programme, écrit une seule fois, sur des plateformes différentes. Le mécanisme prévoit que chaque plateforme, qui supporte Java, dispose de son JRE spécifique. En même temps tous les JRE doivent pouvoir exécuter le même bytecode qui résulte de la compilation des sources Java.

Au fil du temps, des difficultés sont apparus. D’abord le JRE et son élément central, le fichier rt.jar, sont devenus imposants. Dans sa dernière version 1.8, rt.jar pèse 63Mo. En même temps les terminaux légers avec de faibles ressources (tablettes, smartphones, smartwatch..), commencent à prendre une place de plus en plus importante chez les utilisateurs finaux.

La modularisation du JRE dans Java 9 permet, désormais, de créer une image compacte et optimisée capable d’exécuter un programme écrit en Java. Ceci consiste à créer un sous-ensemble du JRE qui ne comprend que le strict nécessaire au cas spécifique de l’application cible.

La suite de cet exposé utilise l’application d’exemple créée dans le premier article qui traite des modules Java. L’application modulaire, exécutable étant créée, on procède à la génération de limage auto exécutable (JRE compris).

Il faut commencer par se positionner dans le dossier où a été créée cette application. Ensuite, céez un sous dossier modules/:

mkdir modules

On crée, ensuite la version modulaire prête à l’emploi de notre application:

jmod create --class-path lib/premiermodule.jar modules/net.meddeb.premiermodule.jmod

Maintenant, on peut créer l’image auto-exécutable de l’application à l’aide de l’utilitaire jlink:

jlink --module-path /usr/lib/jvm/java-9-openjdk-amd64/jmods/:modules/ --add-modules net.meddeb.premiermodule --launcher executeHello=net.meddeb.premiermodule/net.meddeb.hellomodule.Hello --output distribution

Le paramètre –output de cette commande permet de définir le dossier où sera généré le résultat.Dans notre cas on a choisi un dossier qui s’appelle distribution/. Pour explorer le résultat de cette commande et voir ce qui a été généré:

tree -L 2 distribution/

Dans le résultat, remarquez le fichier exécutable executeHello qui est le nom donnée dans la commande de jlink :
modules java
L’exécution se fait par l’intermédiaire de la commande qui suit, comme s’il s’agissait d’un exécutable natif:

distribution/bin/executeHello
Share