Java 14 tombe le masque

Posté par . Édité par theojouedubanjo, olivier-maury, Benoît Sibaud, Davy Defaud et Ysabeau. Modéré par Ysabeau. Licence CC by-sa.
Tags :
36
18
mar.
2020
Java

À quelques jours du printemps, une nouvelle version de Java arrive avec son lot de corrections, améliorations, nouveautés et retraits. Voilà six mois que Java 13 a apporté ses quelques nouveautés. Cette nouvelle itération est bien plus riche aussi bien sur les fonctionnalités définitives que sur celles en cours de maturation. Au programme pas moins de 16 JEP intègrent le langage. Seulement une partie sera détaillée dans la suite de dépêche.

Sommaire

Les nouveautés définitives

Avec la nouvelle cadence de versionnage, les nouveautés arrivent plus tôt mais dans un état non définitif et profitent des retours d’expérience des utilisateurs.

Temps de démarrage et empreinte mémoire

Depuis plusieurs versions, les temps de démarrage et l’empreinte mémoire diminuent. Il est possible d’espérer un gain d’une dizaine de pourcents sur le temps de démarrage, c’est toujours ça de pris ! Côté empreinte mémoire, en revanche, la baisse est plus conséquente, de l’ordre de 30 % à 40 %. Ces améliorations sont natives, il n’est pas nécessaire d’ajouter des options. Pour plus de détails, une présentation et un article.

Du côté des ramasse‑miettes

G1

G1 est le ramasse‑miettes par défaut depuis Java 8 et il progresse de version en version à tous les niveaux (temps de réponse, gestion de la mémoire). Je vous laisse regarder cette présentation ou le support. Cette progression est une bonne raison pour ne plus rester sur Java 8, car aucune amélioration n’est portée sur les versions antérieures.

Les ramasse‑miettes expérimentaux

ZGC (disponible depuis Java 11) fonctionne sur les trois principaux systèmes d’exploitation et il devrait bientôt ne plus être expérimental si l’on en croit cette JEP. L’idée derrière ZGC est de proposer un ramasse‑miettes à faible latence et qui peut aussi bien gérer des petites ou des grosses quantités de mémoire.
Shenandoah est un autre ramasse‑miettes à faible latence intégré depuis Java 12, son objectif est d’avoir des temps de pause identiques quelle que soit la quantité de mémoire à libérer. Si vous voulez savoir comment ça fonctionne et avoir un état d’avancement du projet, je vous laisse regarder cette présentation et pour les explications plus détaillées c’est ici (partie 1), puis là (partie 2).

Switch statement et switch expression

Les switch expression et switch statement sont arrivées dans la version 12, ont été revues dans la version 13 et sont définitives dans cette version 14 (voir la JEP 361).

Avant, on devait écrire :

public enum Event {
    PLAY, PAUSE, STOP
}

String log;
switch (event) {
  case PLAY:
    log = "User has triggered the play button";
    break;
  case STOP:
  case PAUSE:
    log = "User needs a break";
    break;
  default:
    String message = event.toString();
    LocalDateTime now = LocalDateTime.now();
    log = "Unknown event " + message + 
          " logged on " + now;
    break;
}

Et maintenant, cette syntaxe est possible :

var log = switch (event) {
    case PLAY -> "User has triggered the play button";
    case STOP, PAUSE -> "User needs a break";
    default -> {
        String message = event.toString();
        LocalDateTime now = LocalDateTime.now();
        yield "Unknown event " + message + 
              " logged on " + now;
    }
};

Avec cette nouvelle forme :

  • il n’y a plus de risque d’oublier un break en cours de chemin ;
  • il n’est plus nécessaire d’instancier une variable à vide ;
  • c’est plus court !

Autre fait notable, le cas par défaut n’est plus obligatoire lorsque toutes les possibilités d’un enum sont traitées. Par précaution, en rajouter un peut protéger s’il y a un ajout dans l’énumération.

Le mélange des syntaxes est aussi possible avec des risques d’erreurs comme le montre l’exemple suivant :

int i = switch (day) {
    case MONDAY -> {
        System.out.println("Monday"); 
        // ERROR! Block doesn't contain a yield statement
    }
    default -> 1;
};
i = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY: 
        yield 0;
    default: 
        System.out.println("Second half of the week");
        // ERROR! Group doesn't contain a yield statement
};

Chacun se fera son avis sur ces nouvelles formes, car autant un switch case à l’ancienne est pénible à écrire, autant avec les nouvelles possibilités il va falloir s’accorder sur le style à suivre sur un projet.

JDK Flight Recorder Event Streaming

Dans Java 11, Oracle a libéré Flight Recorder (FR) qui permet de suivre l’activité d’une application du sol au plafond, c’est‑à‑dire des appels processeur aux méthodes utilisées pour faire de l’affichage, en passant par le ramasse‑miettes et par le compilateur à la volée. Pour diverses explications, du code et des démos, allez voir cette conférence ou encore cet article. Toutefois, pour découvrir l’outil rapidement, il faut lancer votre application avec java -XX:StartFlightRecording:filename=/tmp/monAppli.jfr -jar monAppli.jar, interagir avec durant quelques instants et l’arrêter. Il est aussi possible de démarrer les enregistrements sur une application déjà en fonctionnement avec jcmd MainClass JFR.start. Ensuite, vous pouvez profiter d’un résumé des évènements enregistrés avec $JAVA_HOME/bin/jfr summary /tmp/monAppli.jfr | less ; pour une analyse plus poussée, Java Mission Control est bien plus adapté.
Le JDK Flight Recorder Event Streaming apporte la possibilité de profiter directement de ces mesures sans passer par la case écriture dans un fichier et lecture à partir de ce dernier. Ça peut sembler basique, mais ça ouvre de nombreuses possibilités pour monitorer de façon déportée différents services (un exemple avec du Grafana et du Quarkus).

Des NullPointerException plus explicites

Dorénavant, les développeurs Java auront moins d’excuses pour passer de longs moments à décortiquer les NPE, car elles indiqueront quel objet est null. Cette fonctionnalité existe depuis 2006 dans le JDK de SAP, et la plus grande ouverture des contributions à Java a permis de la rendre disponible au plus grand nombre. Pour Java 14, il faudra activer l’option -XX:+ShowCodeDetailsInExceptionMessages afin d’en profiter et, à partir de Java 15, l’option sera activée par défaut.

Nouveautés en prévisualisation

Records

La verbosité du langage n’est plus à démontrer et, pour alléger la charge, des efforts sont faits, notamment avec de l’inférence de type avec le mot clé var au moment de déclarer une variable. Les records vont dans ce sens‑là, mais en plus ils permettent de transporter de la donnée de manière immutable. Voici un petit exemple de code :

public record Bouchot(String nom){}

C’est tout, une seule ligne pour créer un record ! Derrière, le langage se débrouille pour générer les méthodes equals(), toString() et hashCode(). Pour accéder au nom d’un bouchot (que l’on aura déclaré comme ceci : var monBouchot = new Bouchot("DLFP"), il suffit de faire monBouchot.nom(). Un record reste une classe Java, avec quelques limitations toutefois, il est donc possible de rajouter des contraintes sur le constructeur, par exemple refuser les null ou écrire votre propre méthode toString(), si la version générée ne vous convient pas.

public record Bouchot(String nom){
  public Bouchot {
    if(null == nom){
      throw new IllegalArgumentException("Crois‑tu qu’une moule puisse s’accrocher à null ?");
    }
  }
}

Une chose intéressante à savoir est que les records ont été définis en prenant en compte le futur du langage aussi bien du côté développeur (types scellés, pattern matching et déconstruction) que de la machinerie interne (inline type). Pour aller plus loin, je vous laisse lire cet article.

Pattern Matching instanceof

Java est le dernier des principaux langages fonctionnant sur la JVM à ne pas implémenter le pattern matching. Pour cette première, il commence modestement en apportant un peu plus de légèreté syntaxique.

// Avant avec le cast
if (obj instanceof Bouchot) {
    Bouchot b = (Bouchot) obj;
    var nom = b.nom();
}

//Après
if (obj instanceof Bouchot b) {
    var nom = b.nom();
}

L’étape suivante est de combiner le pattern matching avec les switch expressions et de pouvoir déconstruire les records. Tout le programme est détaillé dans la JEP 375 et en voici un avant‑goût :

record Point(int x, int y) {}

if (obj instanceof Point(var a, var b)) {
    System.out.println(a+b);
}

Outils d’empaquetage

L’idéal de Java qui était, si je ne me trompe pas, compile ton application une seule fois et elle fonctionnera partout, semble ne plus trop être à l’ordre du jour. La démarche est plus, livre ton application avec les modules Java strictement nécessaires et, optionnellement, le JRE qui va avec. Le but étant la diminution de la taille des applications mais aussi l’amélioration de la réactivité et de la sécurité, car moins de code sera chargé et donc exposé. Comme d’habitude, les détails sont à lire dans la JEP 343.

Les blocs de texte, seconde itération

Après une première implémentation dans la version précédente de Java, en voici une nouvelle (JEP 368). Le principe est d’avoir une solution élégante pour se débarrasser des concaténations sur plusieurs lignes, de se battre avec les échappements divers et variés et surtout améliorer la lisibilité.

String query = """
               SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
               WHERE `CITY` = 'INDIANAPOLIS'
               ORDER BY `EMP_ID`, `LAST_NAME`;
               """;

C’est aussi utilisable en combinaison avec d’autres bibliothèques, voici un exemple d’utilisation avec JOOQ.

Avec cette seconde version, viennent des caractères d’échappement des lignes pour jongler avec les lignes trop longues ou gérer plus finement les retours à la ligne.

Dans l’exemple suivant toutes les lignes feront six caractères :

String colors = """
    red  \s
    green\s
    blue \s
    """;

Les mises au placard et les départs

Ironie de l’histoire, l’architecture créée par la même société que le langage est dépréciée et ne sera rapidement plus supportée. Pour les rares qui ont encore du Solaris et du SPARC, c’est bientôt la fin pour faire tourner des machines virtuelles Java (JVM) modernes. Les détails sont présents dans la JEP 362. Même processus pour le ramasse‑miettes Concurrent Mark Sweep dans le but de laisser plus de temps au développement des autres ramasse‑miettes, les détails dans la JEP 291.

Suppression des outils Pack200, suite à leur placardisation dans Java 11, ils sont remplacés par les outils jlink, plus d’informations dans la JEP 367.

Dans les prochaines versions

La seconde version du pattern matching de instanceof, les types scellés, la version définitive des blocs de texte. Je vous laisse regarder cette diapo de Rémi Forax (un contributeur d’OpenJDK). Pour une vision plus « sous le capot », Brian Goetz (un architecte du langage) a rédigé deux articles sur les évolutions de Java.

Aller plus loin

  • # Je me souviens…

    Posté par (page perso) . Évalué à -2 (+13/-18). Dernière modification le 18/03/20 à 14:56.

    …d'une époque où le public s'intéressait à Java.

    Ça fait un bail !

  • # Java 14 tombe le masque

    Posté par . Évalué à 10 (+14/-1).

    "Java 14 tombe le masque" pas étonnant après que tout le monde l'évite.
    CoronaHumour!
    Je sais, je trolle, désolé.

  • # Et la licence ?

    Posté par . Évalué à 7 (+5/-0).

    Qu'en est il de l'utilisation de ce langage dans le monde du libre ?

    Un éditeur que je connais bien as récemment basculé sur openjdk, bon cela ne concernait que l'outil d'installation mais quand même …

    Note : c'est pas pour polémiquer c'est à titre d'information

    • [^] # Re: Et la licence ?

      Posté par . Évalué à 5 (+3/-0).

      OpenJDK est libre et gratuit. Ensuite il y a les différentes distribution avec une licence, un support et une maintenance qui change selon le fournisseur (IBM, Redhat, Oracle, Azul, AdoptOpenJDK, Amazon etc.).
      Il faut donc trouver le fournisseur adapté aux besoins.

      • [^] # Re: Et la licence ?

        Posté par . Évalué à 3 (+1/-0).

        Merci pour la réponse,

        c'est vrai tout le monde peut developper sa machine virtuelle java a conditions de respecter certaines spécifications … c'est ça

    • [^] # Re: Et la licence ?

      Posté par . Évalué à 7 (+6/-0).

      Qu'en est il de l'utilisation de ce langage dans le monde du libre ?

      Beaucoup de projet dans les fondations eclipse et apache utilisent ce langage par exemple.

      Un éditeur que je connais bien as récemment basculé sur openjdk, bon cela ne concernait que l'outil d'installation mais quand même …

      Je ne comprends pas ce que tu sous-entend ?

      OpenJDK est un projet libre. C'est l'implémentation de référence du JDK et du langage Java. Ils ne fournissent que du code. Il y a des intégrateurs qui sont là pour compiler et mettre à disposition des build. On pense beaucoup aux nouveaux comme Amazon Corretto, mais debian fourni son propre build depuis un paquet d'années, RedHat aussi. L'une des distributions les plus en vogue actuellement (et agnostique de ta distribution linux ou de ton OS) est adoptopenjdk. Le changement qui a eu lieux récemment c'est qu'Oracle n'a plus sa propre implémentation, mais qu'il ne fourni plus qu'une distribution d'OpenJDK.

      « Plus que » il faut voir ce qu'on entends par fournir une distribution (ça marche aussi pour linux ou LaTeX par exemple) :

      • construire et créer les paquets pour la cible que tu cherche
      • suivre les mises à jour et les rendre disponibles ASAP
      • éventuellement fournir des choses en plus (ajouter des outils, fournir plus ou moins de documentation avec)
      • faire tout le suivi de sécurité (est-ce que tu suit simplement la ligne upstream ou est-ce que tu fourni du support plus long terme comme RedHat le fait sur ses paquets ?)

      Selon l'intégrateur que tu choisi se travail peut être fais gratuitement (comme Debian) ou payant (comme RedHat avec RHEL).

    • [^] # Re: Et la licence ?

      Posté par . Évalué à 3 (+2/-0).

      Qu'en est il de l'utilisation de ce langage dans le monde du libre ?

      Pour faire suite aux réponses complètes autour de la licence et des distributions, je me permets de citer quelques exemples de produits populaires construits en Java :
      - Elastic Search (déjà cité) et Lucene sur lequel il est bâti,
      - Cassandra (base de données orientée colonne),
      - Neo4j (base de données orientée graphe),
      - Gerrit (outil de revue de code utilisé par pas mal de projets Google, Wikimedia, entre autres),
      - JOSM (l'éditeur OpenStreetMap),

      Au delà du langage, je souhaiterai pointer qu'un des éléments essentiel de l'écosystème est la JVM elle-même sur laquelle de nombreux langages ont été construits. Les plus connus sont (au doigt mouillé) Kotlin, Scala, Groovy et Clojure. C'est un point notable car cela apporte pas mal de diversité et a permis, par exemple, l'émergence de produits comme Kafka (flux d'évènements distribué) ou Spark (calcul distribué) qui sont fait en grande partie (ou même en totalité ?) en Scala.

  • # Le passé

    Posté par . Évalué à -8 (+11/-20).

    Java c’est le passé. Ça ne survit que par sa base de code énorme et la gestion du legacy dans les gros SI des industriels et administrations. Il existe pléthore de cas où un autre langage fait mieux le job. C#, C++17, Python, Go, Rust, etc…

    Java et sa JVM sont des engeances infâmes qui bouffent des quantités de RAM infernales pour répondre à 3 requêtes HTTP lentement. Oui évidement il est possible de faire de super choses en Java : ElasticSearch, Hadoop, etc… mais la majorité des softs que je vois, ce sont des horreurs sans nom.

    Voilà, moinssez.

    • [^] # Re: Le passé

      Posté par . Évalué à 4 (+5/-2).

      Java et sa JVM sont des engeances infâmes qui bouffent des quantités de RAM infernales
      Ah ben le voilà le jus d orange le passé, un troll RAM sur Java

    • [^] # Re: Le passé

      Posté par (page perso) . Évalué à 5 (+2/-0). Dernière modification le 27/03/20 à 09:51.

      Il existe pléthore de cas où un autre langage fait mieux le job. C#, C++17, Python, Go, Rust, etc…

      Petite revue de ces langages qui font mieux le job:

      • C# est très proche, mais beaucoup moins populaire que Java (surtout dans le monde libre), pas mauvais mais je trouverais beaucoup moins d'aide et de bibliothèques;
      • C++17, j'aime beaucoup C++, mais l'outillage est préhistorique et je m'endors pendant les temps de compilation ;
      • Python est trop primitif (typage dynamique) et trop lent pour mes projets;
      • Go est pas mal, mais aussi trop primitif (pas de généricité);
      • Rust est sympa, mais les frameworks disponibles ne sont pas matures pour mes projets.

      Bref pour des projets qui exigent une solution performante, stable et mature. Java est toujours le champion.

      Incubez l'excellence sur https://linuxfr.org/board/

  • # Guide de l’API Flight Recorder pour les développeurs

    Posté par . Évalué à 4 (+2/-0).

    Oracle a publié un guide avec pas mal d’exemples de code pour utiliser la nouvelle API

    https://docs.oracle.com/en/java/javase/14/jfapi/why-use-jfr-api.html

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.