Disponible depuis le 19 mars 2019, Java 12 est donc un autre petit pas en avant pour Java. Il est à noter que Java 12 n’est pas une version LTS (Long Term Support) comme l’est Java 11 et le sera Java 17. (cf ce précédent article pour mieux comprendre le cycle de releases imposé par Oracle). Elle comporte donc un nombre limité de nouveautés et si vous n’avez pas d’intérêt particulier pour l’une d’entre elles, il est préférable d’attendre un peu avant de l’utiliser pour passer les écueils des releases trop “jeunes”.

Dans cet article, nous avons décidé de vous sélectionner celles qui vous seront les plus utiles au quotidien ou qui vous serviront à anticiper le futur. Nous verrons d’abord une amélioration de la fonctionnalité switch en mode preview, puis quelques optimisations au niveau de la mémoire et du Garbage Collector et enfin d’autres améliorations un peu plus mineures.

Modification des Switch Expressions

Tout d’abord, le mode preview allège la syntaxe Switch Expressions (voir ce lien pour activer le mode preview aux compile et run times avec -enable-preview). Alors que l’ancienne version se lisait de haut en bas, chaque case est maintenant encapsulée, donc plus le problème si vous oubliez un break. Un exemple simple devrait être plus clair. Prenons une to do list avec les activités à faire chaque jour :

Avant Java 12, on écrivait :

switch(jour)
{
	case LUNDI :
		faireLesCourses() ; 
case MERCREDI :  
sortirLesPoubelles() ; 
 	break ; 
case MARDI : 
	entrainementFoot() ; 
break ; 
case VENDREDI : 
	peuPasJaiPiscine() ;
	break ; 
case SAMEDI : 
case DIMANCHE : 
	weekend() ;
break ;  
default : 
	System.out.println(“Rien a faire le jeudi !”)
} 

Avec Java 12, on peut écrire :  

switch(jour)
{	
case LUNDI, MERCREDI -> sortirLesPoubelles() ; 
case LUNDI -> faireLesCourses() ; 
case MARDI -> entrainementFoot() ; 
case VENDREDI -> peuPasJaiPiscine() ;
case SAMEDI, DIMANCHE -> weekend() ;
default  -> System.out.println(“Rien a faire le jeudi !”)
} 

De plus, si on utilise un type d’objet à valeur fini comme le sont les enums, si tous les cas sont couverts, il n’est pas donc nécessaire d’écrire de comportement par défaut.

Enfin, maintenant que chaque case encapsule son propre environnement local, nous n’avons plus le problème avec les noms de variable :

Avant Java 12 :

switch (jour) {
        case LUNDI:
            int temp = ...
            break;
        case MARDI : 
            int temp2 = ...     // Ne peut pas être nommé temp
        case MERCREDI :
            int temp3 = ...     // Ne peut pas être nommé temp ou temp2
    }

Avec Java 12 :

switch (jour) {
        case LUNDI ->
            int temp = ...
            break;
        case MARDI -> 
            int temp = ...     // Ca ne cause pas problème
        case MERCREDI ->
            int temp = ...     // Ca ne cause toujours pas de problème
    }

Il est également possible d’extraire directement une valeur de son enum, ce qui nous permet de faire ceci :

int nombreLettre = switch(jour) {
	case LUNDI, MARDI, JEUDI -> 5 ; 
	case MERCREDI, VENDREDI, DIMANCHE-> 8 ; 
	case SAMEDI-> 6 ;  
}

Nous espérons que les futures versions de Java conserveront cette évolution.

Optimisation de la mémoire et du Garbage collector

Java 12 amène avec lui plusieurs nouveautés concernant le Garbage Collector. Nous allons les lister et les expliciter ci-dessous.

Concurrent Class Unloading

Le Garbage collector peut maintenant libérer l’espace mémoire lié à des classes non utilisées et ainsi réduire l’emprunte mémoire de l’application. Cette fonction est activée par défaut, mais peut être contrôlée avec l’option -XX:-ClassUnloading.

Shenandoah: A Low-Pause-Time Garbage Collector

Java 12 marque aussi l’arrivée au stade expérimental de Shenandoah, un garbage collector créé par RedHat et déjà implémenté dans aarch64 et amd64. Il permet de réduire les temps de pause du GC en permettant une garbage collection en même temps que l’exécution du programme. La taille de la heap n’a donc plus d’impact direct sur les temps de pause. Il peut donc être utile pour des applications pour lesquelles il est intéressant de limiter les temps de réponse et de pause. Toutefois, il n’est pas à privilégier si on cherche une faible empreinte mémoire et à optimiser la vitesse de traitement. Il faut noter que cette fonctionnalité est encore expérimentale donc pour l’utiliser vous devrez activer ces deux flags : -XX:+UnlockExperimentalVMOptions et -XX:+UseShenandoahGC.

Cependant, cette fonctionnalité n’est pas intégrée au build par défaut de openJDK. Donc vous devrez passer par un autre build ou l’ajouter vous-même à votre build perso. D’ailleurs, elle n’est pas une exclusivité de Java 12 malgré qu’elle soit développée en parallèle de cette version. En effet, il est possible d’utiliser Shenandoah sur Java 8 ainsi que 11 en montant. Vous trouverez plus d’informations sur l’installation ici

Allocation of old generation of Java heap on alternate memory devices

Dans le but de prendre avantage des systèmes de mémoire NV-DIMM de plus en plus bon marché, l’équipe Java a décidé de tester l’utilisation de ce type de mémoire en tandem avec la DRAM.  L’ajout d’un flag -XX:AllocateOldGenAt=<path> vous permet de spécifier un chemin vers un répertoire (étant la façon pour le système d’exploitation d’exposer sa mémoire NV-DIMM) pour y allouer les objets old generation. Les objets young generation sont toujours alloués dans la DRAM. Ils seront donc copiés dans cet espace mémoire lors de leur passage dans la old generation.

Encore dans sa phase expérimentale, cette option n’a pas encore d’utilité à proprement parler, et reste un test qui pourrait théoriquement vous libérer un peu de votre DRAM en échange d’un ralentissement minimum (si votre SSD ou autre type de mémoire est assez rapide).

Autres améliorations

Amélioration du CoreSupport de Unicode

Évolution de Unicode 10.0.0 vers Unicode 11.0.0, ce qui permet certaines choses comme des Emojis, des demi étoiles pour les rating : JDK-8209923

Compact Number

Avec l’option Style.SHORT il est possible de montrer des chiffres de façon lisible : JDK-8177552

NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
String result = fmt.format(1000); // = “1K”
String result = fmt.format(1000000 ); // = “1M”

Paramétrage de la JVM : débogage et performances

Rapport d’erreur plus complet

Vous pouvez ajouter le flag -XX+ExtensiveErrorReports. Désormais, on le désactive par défaut.

Désactivation de la sécurité

Il y a également la possibilité de désactiver (java.security.manager) pour des gains de performance.

Activation par défaut des archives CDS

Les archives CDS permettent un partage de la mémoire qui accélère la vitesse de démarrage. Cependant, si la JRE n’a pas été installée par le biais de l’installateur, cette archive n’était pas générée et il fallait la régénérer manuellement via java -Xshare:dump . Désormais, cette fonctionnalité est active par défaut.

Ce n’est qu’un au revoir : les littéraux de chaînes brutes

Un littéral de chaînes brutes s’ouvre avec une séquence d’un ou plusieurs backticks(`). Il se ferme quand une séquence de backticks jointes de longueurs égales est rencontrée. Toute autre séquence est traitée comme faisant partie du corps de la chaîne.

Il permet notamment de rendre certains textes plus simples d’écrire et de lecture.

Par exemple ce texte :

String unTest = `` Hello World\n\W\b /
                Ceci est un ` test
              ``;

Donnerait littéralement :              

  Ceci est un ` test

Déjà présent dans plusieurs langages tels que le C#, C++ et le python, l’équipe JAVA avait décidé de rajouter cette fonctionnalité pour la sortie de Java 12. Cependant, il n’existe pas de solution viable pour cette version. Si cette fonctionnalité vous intéresse, sachez qu’il est très probable qu’on la retrouve dans la prochaine itération.

Et voilà, nous espérons que cette sélection sur les nouveautés de Java 12 aura attisé votre curiosité. Pour les retrouver en intégralité, n’hésitez pas à vous rendre sur la release note de Java 12 ci-dessous.

On se retrouve pour Java 13 !

Référence : https://www.oracle.com/technetwork/java/javase/12-relnote-issues-5211422.html#NewFeature