Nouveautés de Java 9

C’est le 21 septembre 2017 qu’est sorti le la version 9 de Java  (initialement prévue pour le 27 juillet ).

Beaucoup de nouveauté dans cette version : modularisation, interpréteur Java (JShell), simplification du langage (type générique var, …) optimisation, nouvelle API …

Dans cet article j’ai essayé de faire le tour de tous ces changements.

JShell JEP 222

Jshell permet d’exécuter du code Java en ligne sans devoir créer un fichier ou une classe.
Il supporte l’interprétation temps réel des expressions et des boucles Java.

« Modularisation » de Java (Jigsaw)

Maintenant Java permet de créer des modules à la place des jars et les API Java ont elles-mêmes été modularisées.
Le but est de pouvoir indiquer quelle sont les modules que vous avez besoin, et de diminuer la taille de la JVM en ne packageant que les modules que vous avez besoin.
La JVM reste compatible avec les jars.

Attention créer des modules Java n’est pas si simple, car vous devez indiquer qu’elles sont les modules que vous utilisés, vous pouvez aussi indiquer ceux qui peuvent utiliser votre module. Ce n’est intéressant (a mon avis) que si vous voulez faire des runtimes avec juste les modules dont vous avez besoin.

Je vous convie à allez voir l’article suivant https://java.developpez.com/actu/160955/Java-9-est-disponible-la-plateforme-se-met-aux-modules-tour-d-horizon-des-nouveautes/ mais aussi les JEP suivants :

  • JEP 200 : The Modular JDK] (http://openjdk.java.net/projects/jigsaw/spec/[Jigsaw/JSR 376] and http://openjdk.java.net/jeps/261[JEP 261])
  • JEP 201: Modularisation des sources Java
  • JEP 220: Modular Run-Time Images
  • JEP 238: Multi-Release JAR Files
    JEP 259 : Stack-Walking API
  • JEP 261 : Module System
  • JEP 275 : Modular Java Application Packaging
  • JEP 282 : Le Linker Java « jlink » pour créer un runtime

Amélioration des performances du moteur JIT grâce au nouveau G9

JEP 250 : amélioration de la gestion des chaines dans la JVM sur environnement 64bits en optimisant l’usage de la mémoire.

JEP 280 : Modification de la génération de bytecode correspondant à la concaténation de chaine générée par javac. Cela afin de permettra de future optimisation sur la concaténation  de chaine.

Langage JEP 193, 266

  • Inférence du type de variable JEP 193, remplacement de la classe dépréciée "sun.misc.Unsafe » par un équivalent  « java.util.concurrent.atomic »
  • Usage du type « var », qui permet de déclarer une variable par inférence de type.
    Exemple :

     
     
    var list = new ArrayList<String>();

    Créer une variable liste de type ArrayList<String>

    Dans l’exemple suivant :

     
     
    var stream = list.stream();

    la variable stream aura le type Stream<String>

    Milling Project Coin JEP 213

    • Un simple souligné « _ » ne peut plus être utilisé comme un nom de variable.
    • L’annotation « @SafeVarargs » peut être utilisée sur une méthode privée
       
       
      m(new ArrayList<String>());  // WARNING type safety
      ..
      @SafeVarags
      static void m(List<String>... stringLists) { // WARNING type safety
            Object[] array = stringLists;
            List<Integer> tmpList = Arrays.asList(42);
            array[0] = tmpList; // Semantically invalid, but compiles without warnings
            String s = stringLists[0].get(0); // avoid ClassCastException at runtime with @SafeVarags
      }
    • Possibilité d’utiliser une variable finale dans un try-With-Resources sans avoir à le déclarer dans le try
       
       
      FileReader fileReader = new FileReader("mon-fichier.txt");
      ...
      try(fileReader) { // En Java 8:  try( FileReader fileReader = new FileReader("mon-fichier.txt") )
         ...
      }
    • Permettre l’usage de l’opérateur diamant « <> » dans un class Anonyme
       
       
       Comparator<String> stringLengthCompare = new Comparator<>() {
          @Override
          public int compare(String s1, String s2) {
              return s2.length() - s1.length();
          }
      }
    • Possibilité de créer des méthodes privées dans les interfaces. Cela permet de partager du code sur les méthodes non abstraites « default »
       
       
      interface Greeter {
            ...
            default void printColor(String color) {
                  System.out.println("La couleur est " + getColor(color) );
            }
            default void printWhoColor(String who, String color) {
                  System.out.println(who +" est "+ getColor(color) );
            }
            private String getCoor(String color) {
                  return color==null ?return "<no color>": color;
            }
      }

Bibliothèques de base

Amélioration (suppression du côté verbeux) de l’usage des collections JEP 269

  • Maintenant il est possible d’instancier plus simplement les collections avec les méthodes suivantes :
     
     
    List.of(a, b, c);
    Set.of(d, e, f, g);
    Map.of()
    Map.of(key1, value1)
    Map.of(key1, value1, key2, value2)
    Map.of(key1, value1, key2, value2, key3, value3)

Amélioration de l’API des processus JEP 202

  • Maintenant elle permet de récupérer le PID du processus sans avoir à passer par du code spécifique lié au système d’exploitation hôtes :
     
     
    System.out.println(Process.getCurrentPid());
  • Possibilité de lister les processus système au travers de la classe ProcessHandleméthode :
     
     
    ProcessHandle.allProcesses();
  • Possibilité d’obtenir les informations du processus tel que le nom de la commande lancé, ses arguments, l’heure de début et le temps CPU
    Attention, ses informations sont facultatives et basées sur la disponibilité du système d’exploitation.
  • Possibilité  d’obtenir les informations sur les enfants d’un processus, direct et indirect
  • Et le mécanisme de sécurité Java peut permettre ou interdire l’accès à « ProcessHandles »

Dépréciation JEP 277

  • Ajout de deux options à l’annotation @Deprecated : « forRemoval » et « since« .
    Exemple : @Deprecated(forRemoval=true)
    Vous pouvez utiliser les ’annotations @SuppressWarnings("removal") ou @SuppressWarnings({"deprecation", "removal"}) » pour éviter les messages de compilation correspondante
  • Dépréciation des applets
  • Dépréciation de Corba
  • Dépréciation des Interfaces Observer et Observable. A la place, utiliser les classes de « Java.util.concurrent » telles que les files d’attente (queues) ou les sémaphores (semaphores ) pour transmettre des messages entre threads.
  • Dépréciation des méthodes suivante :
    • Boolean(boolean) ,Boolean(String)
    • Byte(byte), Byte(String)
    • Character(char), Double(double)
    • Double(String), Float(float)
    • Float(double), Float(String)
    • Integer(int), Integer(String)
    • Long(long), Long(String)
    • Short(short), Short(String)

Les remplacer par leur équivalent « .valueOf(..) » ou « parse() » de la classe correspondante (ex Boolean.valueOf(true)

Ajout d’un spin-Wait JEP 285

Cette nouvelle méthode « Thread.onSpinWait() » permet d’effectuer des boucles d’attentes en consommant le moins de temps CPU (et d’énergie) dans le cadre ou il est possible d’effectuer des optimisations sur le processeur. Jusqu’à Java 8, nous utilisions un Thread.sleep(0) pour ne pas consommer tous le temps processeur dans cette boucle d’attente infinie (« spin loop« ). Or la méthode sleep() donner la main au processeur, ce qui pouvait générer des attentes (sleep/wait) supérieures à la milliseconde indiquée.

Donc, remplacer touts vos Thread.sleep(0) par  Thread.onSpinWait() afin de fluidifier vos boucles attentes sans consommer.
Voici un exemple de  code :

 
 
void waitMyEvent() {
    while (!myEventIsOK) {
        Thread.onSpinWait();
    }
    //Ici mon événement est OK, je sorts ....
}

 

Variables et méthodes Handle

  • Ajout de « Variable Handles » JEP 193. Je n’ai pas trop compris l’utilité, je vous convie donc à aller voir la note.
  • Amélioration des « Method Handles » JEP 274.
    Amélioration des méthodes « MethodHandle »et « MethodHandles.Lookup » du paquetage java.lang.invoke afin de faciliter les cas d’utilisation courants et permettre au compilateur  d’effectuer des optimisations.

Réseau

Dépréciation des Applet JEP 289

Pratiquement tous les navigateurs modernes ne supporteront plus les applets Java (MS Edge, Chrome, Firefox).
Seules IE et Safarie les supporteront encore pour un certain temps. Et Chrome remplace cette technologie NPAPI par PPAPI (Pepper plugin API).
Oracle indique de remplacer les applets par WebStart.
Les classes correspondantes aux applets seront dépréciées dans le JDK Java 9, elles seront supprimées certainement dans Java 11 (pas Java 10).

Support de HTTP2 et des WebSocket JEP 110.

  • Usage simplifier de l’API HTTP. Par exemple :
     
     
    HttpResponse resp= HttpRequest.create(new URL("https://piradix.com/")).body(noBody()).GET().send();
  • HTTP2, possibilité d’envoyer plusieurs requêtes sur une même connexion HTTP.
  • support de la compression HPACK basé sur le « draft » https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
  • Envoie de requêtes en asynchrone :
     
     
    HttpRequest req=HttpRequest.create(new URL("https://piradix.com/")).body(noBody()).GET();
    req.sendAsync();
    .....
    if( req.isDone() ) { ....}

Moteur JavaScript inclus dans Java

  • Meilleur API de « Parser » JEP236
  • Implémentation de la norme ECMAScript 6 de JavaScript appelé aussi JavaScript ES6 JEP 292

Améliorations de Javadoc

Bibliothèque client

  • Ajout du support des images multi-résolution (JEP 251)au travers de l’interface java.awt.image.MultiResolutionImage et des ses deux méthodes :
     
     
    //retourne une image correspondant à la meilleure représentation de l'image pour la taille demandée en pixel
    Image getResolutionVariant(float destImageWidth, float destImageHeight);
    // retourne une liste des différentes variantes de l'image.
    public List<Image> getResolutionVariants();
  • Ajout du support des images aux formats TIFF JEP 262 en standard sans avoir à utiliser une bibliothèque spécifique tel que JAI.
    La nouvelle API se trouve dans javax.imageio.plugins.tiff.
    Il en est de même pour le support des metada XML du TIFF, avec une classe similaire .
    En résumé, Java 9 supporte nativement les formats image suivant PNG, JPEG et TIFF.
  • Une API pour mieux accéder aux spécifications du bureau du système d’exploitation (icône application,Intégration du Dock, l’écran passe en veille) JEP 272.
    Ces nouvelles méthodes sont intégrées dans la classe java.awt.desktop.
    Pour plus d’information, aller voir sa documentation : http://download.java.net/java/jdk9/docs/api/java/awt/desktop/package-summary.html

Interface graphique : JavaFX

Outils et instruction de diagnostic

  • Ajout d’instruction de diagnostic JEP 228
  • Suppression des outils de diagnostic « hprof » JEP 240 et « jhat » JEP 241, car il existe d’autres outils bien plus performants .
    Essayer l’outil jVisualVM (BRUNO mettre lien)

Options de la JVM

  • JEP 214 : Suppression de combinaison précédemment déprecated dans le JDK 8
  • JEP 245 : Meilleur validate des flag de la JVM
  • JEP 248 : « G1 » devient le « Garbage Collector » de défaut

Logging

  • Unification des logs pour tous les composants de la JVM. les logs sont contrôlables au travers du paramètre -Xlog. Voir le JEP 158 .
  • JEP 264 : Definition d’un API de log minimal
  • JEP 271 : réimplementation et uniformisation du loggin du GC

Divers

  • Support d’Unicode 7 JEP 227 et 8 JEP 267
  • Support de « Datagram Transport Layer Security » (DTLS). Algorithme de cryptage que peut utiliser les WebRTC et HTTPS JEP 219.
  • Simplification de la déclaration de beanInfo (JEP 256) en remplaçant l’annotation @beaninfopar par l’usage @interface comme ceci :
    package java.beans;
    
    public @interface JavaBean {
        String description() default "";
        String defaultProperty() default "";
        String defaultEventSet() default "";
    }
    
    package java.beans;
    
    public @interface BeanProperty {
        boolean bound() default true;
        boolean expert() default false;
        boolean hidden() default false;
        boolean preferred() default false;
        boolean visualUpdate() default false;
        String description() default "";
        String[] enumerationValues() default {};
    }
    
    package javax.swing;
    
    public @interface SwingContainer {
        boolean value() default true;
        String delegate() default "";
    }
  • JEP 260 : Encapsule plus API interne
  • JEP295 : Compilez les classes Java en code natif avant de lancer la machine virtuelle.

Vous pouvez aussi allez voir les articles suivant :