Installer Java 9 sur Debian Stretch

Java 9 constitue une évolution majeure de ce language de programmation / environnement d’exécution. L’évolution la plus importante apportée par cette version est sans doute l’introduction de la notion de module.  Cette introduction a nécessité un changement radical dans la structure de son environnement d’exécution (JRE) mais aussi de son kit de développement (JDK). Ce changement constitue une véritable rupture dans la façon de concevoir une application ou une librairie Java.

Malgrès les précautions prises et l’effort manifeste qui a été déployé pour assurer une migration en douceur de l’énorme quantité de code déjà en utilisation de ce système, cette migration reste compliquée et sera certainement assez étalée dans le temps (Java 9 est sorti en Septembre 2017). A l’heure actuelle, du fait de la rupture entre Java 1.8- et Java 9+, migrer les systèmes serveurs à Java 9+ est un exercice risqué. En même temps il est nécessaire d’effectuer des tests en profondeur avec cette version sur les applications et les librairies existantes pour pouvoir les faire évoluer.

Le système GNU/Linux Debian, destiné principalement à des machines serveurs et fidèle à son attachement à la stabilité, n’est toujours pas passé à Java 9 et ne le sera, probablement, pas de sitôt. Toutefois il y a toujours la possibilité d’installer cette version de Java pour pouvoir effectuer des tests comme indiqué.

Ce tutoriel montre la manière offerte par ce système pour installer la version 9 de Java.

1. Le dépôt backports de Debian

Java 9 a été retiré du dépôt backports de Debian, certainement à cause d’incohérence constatée avec le reste du système, notament avec des interfaces graphiques. Cette méthode n’est donc  plus applicable pour Debian Stretch. Toutefois la démarche pour l’installation de paquets expérimentaux reste valable.

Pour effectuer des expérimentations  Java 9+ sur Debian il convient d’utiliser plutôt la version Buster (10) de cet OS, version encore en développement à ne pas utiliser en production.

A l’installation d’un système Debian le fichier /etc/apt/sources.list référence les dépôts des paquets d’installation et de mise à jour du système. Dans ce fichier et vers la fin, on trouve:

# stretch backports
#deb http://http.debian.net/debian stretch-backports main

La première ligne est le commentaire qui donne le nom de ce dépôt. C’est la deuxième ligne qui le référence. Si elle n’a pas été modifiée, cette ligne est commentée et ce dépôt est donc désactivé. La raison pour laquelle ce dépôt est désactivé par défaut est qu’il contient des fonctionnalités en version jugée insiffisament stable ou pouvant introduire des instabilités ou encore au stade expérimental. Ce dépôt ne doit pas être utilisé pour un système en production.

A l’heure actuelle (Octobre 2018) Java 9 est dans cette situation du point de vue de Debian. Cette version se trouve donc dans ce dépôt. Vérifions le, cette ligne étant commentée et Java 9 n’ayant jamais été installé sur le système utilisé, exécuter les commandes:

sudo apt update
apt-cache search openjdk | grep -E ^openjdk-[0-9]*-jdk\|jre

La réponse à la deuxième commande sera:

default-jre - Standard Java or Java compatible Runtime
default-jre-headless - Standard Java or Java compatible Runtime (headless)
openjdk-8-jdk - OpenJDK Development Kit (JDK)
openjdk-8-jdk-headless - OpenJDK Development Kit (JDK) (headless)
openjdk-8-jre - OpenJDK Java runtime, using Hotspot JIT
openjdk-8-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless)
openjdk-8-jre-zero - Alternative JVM for OpenJDK, using Zero/Shark
openjdk-8-jre-dcevm - Alternative VM for OpenJDK 8 with enhanced class redefinition

Seule la version 1.8 est disponible.

2. Installation de la version 9

Pour pouvoir installer la version 9 de Java, il convient d’activer le dépôt backports. Cela se fait en décommentant la ligne qui le référence dans le fichier de configuration des dépôts des paquets système. On peut le faire avec un éditeur de texte ou avec la commande:

sudo sed -i '/^#.*backports /s/^#//' /etc/apt/sources.list

Après cela on refait une recherche des versions disponibles:

sudo apt update
apt-cache search openjdk | grep -E ^openjdk-[0-9]*-jdk\|jre

Le résultat sera alors:

default-jre - Standard Java or Java compatible Runtime
default-jre-headless - Standard Java or Java compatible Runtime (headless)
openjdk-8-jdk - OpenJDK Development Kit (JDK)
openjdk-8-jdk-headless - OpenJDK Development Kit (JDK) (headless)
openjdk-8-jre - OpenJDK Java runtime, using Hotspot JIT
openjdk-8-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless)
openjdk-8-jre-zero - Alternative JVM for OpenJDK, using Zero/Shark
openjdk-8-jre-dcevm - Alternative VM for OpenJDK 8 with enhanced class redefinition
openjdk-9-jdk - OpenJDK Development Kit (JDK)
openjdk-9-jdk-headless - OpenJDK Development Kit (JDK) (headless)
openjdk-9-jre - OpenJDK Java runtime, using Hotspot JIT
openjdk-9-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless)

La version 9 est maintenant bien disponible à l’installation. Pour l’installer:

sudo apt install openjdk-9-jdk-headless 

L’installation du JDK 9 positionne également cette version comme étant la version par défaut. Pour s’en rendre compte, pour l’environnement d’exécution (JRE) et le compilateur Java:

java -version # JRE
javac -version # compilateur 

Les deux sont bien à la version 9 fraichement installée.

3. Basculer entre les versions 9 et 1.8

S’agissant d’une installation d’expérimentation, on peut bien avoir besoin de basculer entre les deux versions installées. Pour cela on utilise l’utilitaire update-java-alternatives. Exécuter:

sudo update-java-alternatives --list

La réponse sera alors:

java-1.8.0-openjdk-amd64       1081       /usr/lib/jvm/java-1.8.0-openjdk-amd64
java-1.9.0-openjdk-amd64       1091       /usr/lib/jvm/java-1.9.0-openjdk-amd64

Le numéro correct de la version est 9 et non 1.9 car Java a changé la politique du numéro de version à partir de celle là. Debian, pour le moment, ne semble pas en tenir compte mais cela sera peut être rectifié à l’avenir. En tout cas cela n’empêche rien de fonctionner. L’élément important dans ce résultat est la première colonne. le nom affiché dans cette colonne sert à définir la version par défaut. Pour basculer vers la version 1.8:

sudo update-java-alternatives --set java-1.8.0-openjdk-amd64

La valeur utilisée pour le paramètre –set est le nom affiché dans la première colonne de la liste.

Share

Eclipse et les modules Java

Ce tutoriel Eclipse a pour objectif de montrer les fonctionnalités de cet IDE en relation avec la gestion des modules. Eclipse, dans sa version Photon – 4.8 (Juin 2018), inclu des fonctionnalités de configuration des projets Java pour prendre en charge la notion de module introduite en Java 9.

1. Un projet de démonstration

Dans eclipse créer un nouveau projet Java: Sélectionner le menu : File / New / Project.Sélectionner Java Project. Ensuite, l’utilisation du bouton Next permet d’accéder à la fenêtre de configuration du projet.
eclipse modules java

Saisir le nom du projet et sélectionner la version 9 de Java au minimum comme cible d’exécution. Utiliser le bouton Finish pour lancer la création du projet. A ce stade, une fenêtre s’affiche pour suggérer la création du fichier descripteur de module module-info.java du projet:

eclipse modules java

Si on aurait choisit Java 1.8 ou inférieur comme version cible d’exécution, cette fenêtre ne s’afficherait pas. Pour le besoin de démonstration, on va décliner cette offre et continuer avec un projet compatible Java 1.8 et inférieur. On clique donc sur Don’t Create et Eclipse génère le projet comme demandé.

Sélectionner le nouveau projet dans l’explorateur de package (volet de gauche) et faire un click droit de la souris puis accéder au menu de création d’une nouvelle classe: New / Class.

eclipse modules java

Ce menu mène à la fenêtre de cration d’une nouvelle classe:

eclipse modules java

Eclipse ajoute le fichier de la nouvelle classe qu’il convient de compléter comme suit (ligne à rajouter):

eclipse modules javaA ce statde la création du projet de démonstration est terminée. On peut l’exécuter pour afficher le message de test. On se propose dans la suite de transformer ce projet en module Java.

2. Le fichier descripteur de module

Si le projet Eclipse est un module Java, il faudra qu’il inclut le fichier descripteur de module module-info.java dans la racine du projet (voir l’article à ce sujet). Une fonctionnalité Eclipse permet de créer ce fichier.

eclipse modules java

Click droit sur le projet, ensuite Configure / Create module-info.java. L’utilisation de ce menu permet d’accéder à la même fenêtre de création de module rencontrée à la première génération du projet. Dans cette fenêtre saisir net.meddeb.eclipsemoduletuto comme nom de module et valider avec le bouton Create.

eclipse modules java

Eclipse génère, alors, le fichier descripteur de module avec le nom saisi. Ce fichier généré exporte l’unique package de notre projet. On constate que cette transformation en module ne change rien à cette application et elle continue à s’exécutable de la même manière. Pour le besoin de démonstration, on va faire évoluer cette application de manière qu’elle affiche un autre message en passant par l’API de logging de Java. Modifier le fichier de la classe Mainclass pour que son contenu devienne (copier / coller):

package net.meddeb.eclipsemoduletuto;
import java.util.logging.Logger;
public class Mainclass {
  public static void main(String[] args) {
    System.out.println("Hello eclipse Java !"); 
    Mainclass m = new Mainclass();
    m.afficherMessage();
  }
  public void afficherMessage() {
    final Logger logger=Logger.getLogger(this.getClass().getPackage().getName());
    logger.info("Hello eclipse Java module !");
  }
}

Après cette modification la compilation de l’application échoue. La raison est que le package java.util.logging utilisé par cette modification n’est pas accessible du fait de la modularisation du code. La solution est de déclarer implicitement le besoin de notre application/module à ce package. Pour le faire, modifier le fichier descripteur de module de manière que son contenu devienne:

module net.meddeb.eclipsemoduletuto {
  exports net.meddeb.eclipsemoduletuto;
  requires java.logging;
}

L’explication est que le code supplémentaire utilisé se trouve dans le package  java.util.logging, exporté par le module du JRE java.logging. Pour pouvoir l’utiliser il faudra inclure ce module dans une clause requires du fichier descripteur. Une question légitime se pose dans ces conditions: pourquoi l’application se compilait et s’exécutait sans problème avant cette modification, alors qu’aucune clause requires n’a été utilisée ?

La réponse à cette question est que le code de définition de la classe et le code de System.out utilisé pour l’affichage du message se trouvent dans le module de base du JRE java.base. C’est l’unique module qui est référencé implicitement et n’a pas besoin de figurer explicitement dans une clause requires du module qui l’utilise.

D’un autre côté, pour que la compilation et l’exécution donctionnent, l’emplacement des fichiers des modules utilisés doit figuer dans le chemin de recherche des modules: le Modulepath.

3. Modulepath et Classpath

Faire un click droit sur le projet dans le volet de gauche, puis accéder au menu Build Path / Configure Build Path..

eclipse modules java

La fenêtre de configuration des chemins de construction du projet apparaît et on peut remarquer l’existence de deux types de chemins. Le chemin des modules utilisés Modulepath et le chemin de compatibilité le Classpath.eclipse modules java

Eclipse a référencé pour nous la totalité du JRE cible de l’exécution dans le Modulepath du projet. Ouvrir le contenu de ce JRE, les deux modules utilisés par le projet apparaîssent bien dans cet endroit:

Share

Modules Java: Présentation et concepts

Dans sa version 9, Java a introduit une évolution conceptuelle importante: les modules. Cet article a pour objectif d’expliquer ce nouveau concept, ses raisons d’être et surtout son utilité.

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. Cet article: Modules Java: Présentation et concepts
  2. Modules Java: JRE modulaire
  3. Modules Java: Une application exemple – Conception
  4. Modules Java: Une application exemple – Intérêts

1. La programmation orientée objet et l’encapsulation

Java s’inscrit entièrement dans la programmation orientée objet (POO). Mis à part les 8 types de données primitives et qui ont tous un correspondant objet, dans Java, tout est objet. La POO est basée sur un certain nombre de concepts parmis lesquels le concept d’encapsulation vise à favoriser la robustesse et la modularité du code. Ce concept consiste, principalement, à cacher les détails des données (champs) et des traitements (méthodes) à l’intérieur de l’objet lui même. Concrètement, cela consiste à déclarer ces détails avec les modificateurs de visibilité private ou protected. Cela consiste, par conséquent, à ne laisser accessible de l’extérieur de l’objet que le strict nécessaire à son utilisation. Cela veut dire, ne déclarer avec le modificateur public que le strict nécessaire à l’utilisation externe.

Un objet d’une classe conçue en conformité avec ce principe de la POO, peut être modifié sans aucune conséquence pour les reste du code, tant qu’on ne modifie pas le format de sa partie publique. Cela dote l’application d’une grande robustesse et évolutivité au cours de son cycle de vie, car le code d’une application a toujours besoin d’être modifié pour corriger des anomalies ou faire évoluer son fonctionnement.

2. Extension de la notion d’encapsulation

Dans la pratique, il s’est avéré que la classe est d’une granularité trop faible au sein d’un logiciel pour pouvoir assurer une réutilisabilité et une robustesse suffisante. Ceci est la conséquence naturelle de la compléxité et la taille grandissantes des logiciels à construire. De nos jours, une application moyenne peut rapidement atteindre plusieurs centaines de classes. Pour cela le niveau d’abstraction de l’encapsulation gagnerait en efficacité s’il est étendu à un niveau plus élevé: Le package, qui regroupe plusieurs classes dans un seul espace de noms.

Dans un package, une classe peut être déclarée:

  • Avec le modificateur public: ses méthodes et ses champs publiques sont accessibles à partir des autres packages.
  • Sans modificateur: N’est pas accessible à partir des autres packages.

Ceci fait du package une unité de modularisation possible d’un code logiciel. On peut considérer une bibliothèque/composant logiciel composée d’un package unique où une ou plusieurs classes publiques constituent l’interface du composant et d’autres classes non publiques chargées des détails internes à cette bibliothèque/composant.

Malgrés une nette amélioration apportée par ce nouveau niveau d’abstraction, cette extension reste insuffisante, notamment pour les raisons suivantes:

  • La nouvelle unité modulaire est forcément mono-package.
  • Absence de règles explicites de dépendance entre packages.
  • Absence de toute vérification préalable de cohérence entre unités modulaires.

Notamment, la dernière raison évoquée engendre la possibilité de conflits détéctables seulement pendant l’exécution, engendrant ainsi des erreurs d’exécution. Ce problème est connu sous le nom de JAR Hell ou l’enfer des JARs.

3. Les modules en Java 9

Les modules introduits en Java 9 portent la possibilité d’encapsulation à un niveau d’abstraction encore plus élevé. C’est au niveau physique du fichier JAR que l’encapsulation peut s’effectuer. Mais au delà de l’encapsulation, une modularisation avancée du code applicatif devient possible grâce aux caractéristiques des modules Java:

  • Groupement de code applicatif sous forme d’une collection de packages de tailles quelconques.
  • Le module peut contenir aussi du code natif, des fichiers de configuration et des ressources statiques.
  • Visibilité externe déclarative de type exports/requires qui permet la construction facile d’un arbre de dépendance.
  • Vérification, préalable à l’exécution, de la cohérence des inter-dépendances entre modules.

Concrètement, un fichier JAR/module ne diffère d’un fichier JAR classique que par l’existence à sa racine d’un fichier qui s’appelle impérativement module-info.java. Ce fichier contient une définition déclarative du module.

4. Création d’un module Java

Avec un éditeur de texte, créer le fichier Hello.java dont le contenu est:

package net.meddeb.hellomodule;
class Hello {
  public static void main(String[] args) {
    System.out.println("Hello module in world !");
  }
}

Et le fichier module-info.java dont le contenu est:

module net.meddeb.premiermodule {
  exports net.meddeb.hellomodule;
}

Ensuite, compiler le code et créer le fichier JAR du module en exécutant cette série de 3  commandes dans l’odre indiqué:

javac -d classes Hello.java module-info.java
mkdir lib
jar -c -M -f lib/notrepremiermodule.jar -C classes .

Voilà! On vient de créer notre premier module Java 9 dans le dossier lib/

  • Ce module s’appelle net.meddeb.premiermodule, mais le nom peut être quelconque. Dans la pratique il vaut mieux le préfixer par un nom de domaine pour l’unicité universelle.
  • Le fichier JAR qui contient le module s’appelle: notrepremiermodule.jar
  • Il contient un seul package net.meddeb.hellomodule, qui contient lui-même une seule classe Hello.
  • Il exporte son unique package: déclaration exports dans le fichier module-info.java

Vérifier le contenu du fichier JAR de ce module. Exécuter:

jar tvf lib/notrepremiermodule.jar

Alors, la réponse est:

   233 Wed Sep 26 21:26:36 CEST 2018 module-info.class
     0 Wed Sep 26 21:26:22 CEST 2018 net/
     0 Wed Sep 26 21:26:22 CEST 2018 net/meddeb/
     0 Wed Sep 26 21:26:22 CEST 2018 net/meddeb/hellomodule/
   450 Wed Sep 26 21:26:22 CEST 2018 net/meddeb/hellomodule/Hello.class

Maintenant, on peut exécuter la classe Hello de deux manières différentes. En tant que classe exécutable (contenant la méthode main()) dans un fichier JAR quelconque, compatibilité ascendante oblige:

java --class-path lib/notrepremiermodule.jar net.meddeb.hellomodule.Hello

On peut l’exécuter, également, en tant que classe exécutable contenue dans un module:

java --module-path lib/ -m net.meddeb.premiermodule/net.meddeb.hellomodule.Hello

Cette deuxième commande ne fonctionne qu’en JAVA 9+. Le succès de son exécution, montre que le JRE reconnait bien notre module en tant que tel. Elle ne fonctionnera pas si on enlève du  JAR le fichier module-info.class. Vous pouvez le tester, il suffi de repackager le JAR sans ce fichier.

Share

Tutoriel JShell: Personnalisation et import de librairies externes

Ce tutoriel JShell aborde des aspects avancés de l’utilisations de cet outil. On y traitera les sujets de l’import et le référencement de bibliothèques (et de modules) externes à la JRE ainsi que celui de la personnalisation de l’outil.

Ce tutoriel fait partie d’une serie de quatre articles qui permettront de se familiariser, suffisament, avec JShell afin de pouvoir l’utiliser efficacement et augmenter la productivité avec le langage de programmation Java:

  1. Tutoriel JShell: Installation et concepts
  2. Tutoriel JShell: Utilisation
  3. Tutoriel JShell: Scripts et scripts de démarrage
  4. Cet article: Tutoriel JShell: Personnalisation et Import de librairies externes

1. Import de packages supplémentaires

Lancer JShell sans aucun script de démarrage, sans même DEFAULT. Ceci est possible grâce à la commande:

jshell --no-startup

Ensuite exécuter les deux instructions Java suivantes, l’une après l’autre:

String nomfichier = "fichiertest.txt"
Files.write(Paths.get(nomfichier), "Le contenu du fichier de test\n".getBytes());

La première instruction s’exécute sans erreur. La raison est que la classe String est dans le package java.lang qui n’a pas besoin d’être importé explicitement.

En revanche, la deuxième instruction échoue car les classes Files et Paths sont dans le package java.nio.file. Comme dans les programmes Java, pour utiliser ce package dans JShell, on doit d’abord l’importer. Exécuter maintenant:

import java.nio.file.*
Files.write(Paths.get(nomfichier), "Le contenu du fichier de test\n".getBytes());

Astuce: La deuxième commande peut être rappelée avec la touche flèche haut du clavier comme dans le shell système.

Maintenant, cette commande s’exécute et crée le fichier fichiertest.txt avec le contenu demandé. Pour vérifier, quitter JShell et retrouvez ce fichier dans le dossier courant.

2. Import de packages et bibliothèques externes

De la même manière que pour les packages Java, on peut référencer les packages d’une bibliothèque externe. Pour pousser cette logique à son extrême, on va créer une « bibliothèque » Java personnelle. Pour simplifier, cette« bibliothèque » sera composée d’une seule classe mais packagée dans un fichier JAR comme il se doit. A l’aide d’un éditeur de texte, créer le fichier Multiplication.java dont le contenu est:

package net.meddeb.mult;
public class Multiplication {
  public void table(int i) {
    for (int j=1; j<=9; j++) {
      System.out.printf("%d x %d = %d\n", i, j, i*j);
    }
  }
}

C’est l’unique classe qui compose la « bibliothèque » de notre exemple. Elle ne contient qu’une methode unique qui affiche la table de multiplication de l’entier passé en paramètre. On va compiler et packager dans le fichier multip.jar cette classe. Ensuite on va l’installer dans un dossier lib/, sous dossier de notre dossier de travail. Pour faire tout cela, exécuter dans l’ordre:

javac Multiplication.java
mkdir -p net/meddeb/mult/
mv Multiplication.class net/meddeb/mult/
jar -c -f multip.jar -M net/
mkdir lib/
mv multip.jar lib/

Pour pouvoir utiliser cette « bibliothèque » personnelle avec JShell, on doit le lancer avec la commande:

jshell --class-path lib/multip.jar

Pour tester l’utilisation de la classe Multiplication, exécuter dans l’ordre:

import net.meddeb.mult.*
Multiplication m = new Multiplication()
m.table(8)

Le paramètre de lancement –class-path permet d’indiquer un ou plusieurs packages externes (à la JRE). Ce paramètre peut également être positionné dans l’environnement JShell grâce à la commande /env. Ceci est particulièrement intéréssant pour inclure ce paramètre dans un script de démarrage par exemple ou même dans un script tout court. Un exemple: créer le fichier de script mult5.jsh dont le contenu est le suivant:

/env -class-path lib/multip.jar
import net.meddeb.mult.*;
Multiplication m = new Multiplication();
m.table(5);
/exit

Ensuite exécutez le avec la commande simple:

jshell mult5.jsh

De la même manière on peut importer des modules, au sens du nouveau concept introduit par Java 9 du terme module. Ceci peut être fait grâce aux paramètres –module-path et –add-modules.

3. Personnalisation de l’environnement JShell

Cette personnalisation consiste en la modification à souhait du mode de retour d’information ou feedback. Il existe trois paramètres à modifier pour le retour d’information: le prompt ou le message d’attente, la troncature et le format. Un mode natif de JShell ne peut pas être supprimé mais on peut le copier, modifier cette copie et l’activer à la place du mode natif. Ensuite le mode natif peut être réactivé à tout moment.

3.1. Personnalisation du message d’attente (prompt)

Dans l’environnement JShell exécuter:

/set prompt

La réponse à cette commande est:

|  /set prompt normal "\njshell> " "   ...> "
|  /set prompt silent "-> " ">> "
|  /set prompt concise "jshell> " "   ...> "
|  /set prompt verbose "\njshell> " "   ...> "

Il s’agit de la liste des formats du message d’attente pour les quatres modes de retour d’information prédéfinis: normal, silent, concise et verbose.  Pour commencer la personnalisation, on va copier le mode normal pour créeer le mode personnalisé modetuto. Pour cela exécuter:

/set mode modetuto normal -command

Maintenant, on peut modifier le message de prompt de ce mode pour le personnaliser. Deux paramètres sont à modifier: le message d’attente normal et celui à utiliser dans le cas de saisie de plusieurs lignes de suite, comme dans le cas de céation de méthode. Exécuter:

/set prompt modetuto "\n[Tutoriel JShell:] "  "[...............:] "

Pour tester le nouveau prompt, il faut l’activer:

/set feedback modetuto

JShell passe immédiatement au nouveau mode qui est identique au mode normal sauf en ce qui concerne le message de prompt car on l’a modifié.

3.2. Personnalisation de la troncature

Le paramètre de troncature permet de personnaliser l’affichage des valeurs trop larges (généralement des chaines de caractères) en tronquant cet affichage. Exécuter:

/set truncation modetuto

Le retour de cette commande indique les valeurs actuelles de ce paramètre qui sont hérités du mode normal. Ces valeurs veulent dire:

  1. Toute valeur à afficher dont la taille est supérieure ou égale à 80 caractères sera tronquée.
  2. Une exception est faites pour l’affichage des expressions qui ne sera tronquée qu’à partir de 1000 caractères.

Pour tester ce comportement, exécuter:

String b = String.join("", Collections.nCopies(7, "abcdefghij"));
String b = String.join("", Collections.nCopies(8, "abcdefghij"));
System.out.println(String.join("", Collections.nCopies(8, "abcdefghij")));

abcdefghij, sont les 10 premiers caractères de l’alphabet. La première instruction permet de dupliquer cet ensemble de caractères 7 fois, ce qui donne 70 caractères. Le résultat de cette instruction n’est pas tronqué. En revanche celui de la deuxième instruction qui donne 80 caractères est tronqué.

La troisième instruction affiche le résultat d’une expression, la limite est donc repoussée à 1000, c’est pour cela que le résultat de cet affichage n’est pas tronqué.

Modifions maintenant ce paramètre:

/set truncation modetuto 30
String b = String.join("", Collections.nCopies(3, "abcdefghij"));

La deuxième instruction permet de vérifier que la troncature est bien effectuée à partir de 30 caractères.

3.3. Personnalisation du format

Exécuter dans l’environnement JShell:

/set format modetuto

La réponse montre la richesse et la compléxité de ce paramètre. Ceci provient du fait qu’il concerne l’affichage des messages de retour des commandes dans différentes circonstances. Faute de pouvoir aborder les détails de ce paramétrage, on va se contenter d’un un exemple. Pour le détail il faudra consulter l’aide de ce paramètre qui peut être affiché avec:

/help format

Pour l’exemple, exécuter:

import java.net.*

Cette commande ne retourne aucun message d’information, même pas pour dire que tout s’est bien passé. On peut remedier à cela en personnalisant le paramètre format de notre modetuto:

/set format modetuto display "{pre}added import {name}{post}" import-added
/set format modetuto display "{pre}re-added import {name}{post}" import-modified,replaced

Après cela, exécuter une deuxième fois la commande d’import. Grâce à cette personnalisation, on a désormais un message de retour claire.

4. Persistence de la personnalisation de l’environnement JShell

Si on quitte JShell après avoir personnalisé l’environnement tel que cela a été vu dans le paragraphe précédent, la personnalisation sera perdue. Pour faire perdurer ce paramétrage il faudra exécuter:

/set mode modetuto -retain

Avec cette commande, même si on quitte JShell, le paramétrage modetuto n’est pas perdu mais ne sera pas activé par défaut au démarrage. Pour le rendre actif de manière permanente, il faudra exécuter:

/set feedback modetuto -retain
Share