Java 15 : quoi de neuf ?
Maintenant que Java 15 est features complete (Rampdown Phase One au jour d’écriture de l’article), c’est le moment de faire le tour des fonctionnalités qu’apporte cette nouvelle version, à nous, les développeurs.
Cet article fait partie d’une suite d’article sur les nouveautés des dernières versions de Java, pour ceux qui voudraient les lire en voici les liens : Java 14, Java 13, Java 12, Java 11, Java 10, et Java 9.
Cette nouvelle version apporte son lots de nouvelles JEP, dont la principale est l’ajout des Sealed Classes. Les Records et le Pattern Matching introduits en Java 14 restent en preview dans cette version.
JEP 360 : Sealed Classes
Les Sealed Classes permettent de limiter le nombre d’implémentations d’une classe ou d’une interface à une liste prédéfinie. La hiérarchie de cette classe/interface est donc close (scellée / sealed).
Comme cette hiérarchie est connue à la compilation, cela ouvre des possibilités pour le Pattern Matching, une future implémentation de switch basé sur le type d’un objet est prévue dans une des prochaines versions de Java. Cela permet aussi à l’auteur d’une classe/interface d’exprimer son utilisation de manière plus fine que via les modificateurs de visibilité en restreignant son utilisation à une liste précise.
Voici des exemples d’utilisation extraits de la JEP
package com.example.geometry;
public sealed class Shape
permits Circle, Rectangle, Square {...}
Si les classes sont déclarées dans le même fichier source, la clause permits
peut être ignorée.
package com.example.geometry;
sealed class Shape {...}
class Circle extends Shape {...}
class Rectangle extends Shape {...}
class Square extends Shape {...}
Maintenant qu’on connaît la liste des classes implémentant une interface, on peut écrire plus facilement une suite de if/else sur la classe Shape
:
Shape rotate(Shape shape, double angle) {
if (shape instanceof Circle) return shape;
else if (shape instanceof Rectangle) return shape.rotate(angle);
else if (shape instanceof Square) return shape.rotate(angle);
}
Quand le Pattern Matching aura été étendu pour couvrir les Sealed Classes, on pourra alors écrire un switch avec un test sur le type d’un objet:
Shape rotate(Shape shape, double angle) {
return switch (shape) {// won't compile in Java 15 ...
case Circle c -> c; // no action needed
case Rectangle r -> r.rotate(angle);
case Square s -> s.rotate(angle);
}
}
Un nouveau mot clé a été introduit non-sealed
qui permet d’ouvrir la hiérarchie depuis une des sous-classes ou sous-interfaces d’une Sealed Class.
Autres nouveautés
- JEP 339: Edwards-Curve Digital Signature Algorithm (EdDSA). Implémentation de l’algorithme de cryptographie EdDSA.
- JEP 373: Reimplement the Legacy DatagramSocket API. Après avoir ré-implémenté les
java.net.Socket
etjava.net.ServerSocket
dans Java 13, c’est au tour desjava.net.DatagramSocket
etjava.net.MulticastSocket
. La motivation est la même, remplacer une implémentation vieillissante et difficile à maintenir par une implémentation plus récente pour faciliter la future implémentation des Lightweight Threads du projet Loom. - JDK-8244441: Support de l’extension
certificate_authorities
pour TLS 1.3. - JDK-8215401:
CharSequence.isEmpty()
.
Les fonctionnalités qui passent de preview à standard
Les fonctionnalités suivantes, qui étaient en preview sont maintenant en standard, pour les détails sur celles-ci vous pouvez vous référer à mes articles précédents.
- JEP 377: ZGC: A Scalable Low-Latency Garbage Collector
- JEP 379: Shenandoah: A Low-Pause-Time Garbage Collector
- JEP 378: Text Blocks
- JEP 358: Helpful NullPointerExceptions. La JEP 358 nous a offert des messages d’erreur plus compréhensibles pour les
NullPointerException
dans Java 14. À mon grand regret cette fonctionnalité était désactivée par défaut. Elle est maintenant activée par défaut (via JDK-8233014) et c’est une très bonne nouvelle !
Les fonctionnalités qui restent en preview
Les fonctionnalités suivantes restent en preview.
- JEP 375: Pattern Matching for instanceof. Pas de changement dans cette version mais la fonctionnalité reste en preview car des changements sont prévus pour les versions suivantes de Java.
- JEP 383: Foreign-Memory Access API. Amélioration et refactoring de la fonctionnalité.
- JEP 384: Records. L’implémentation a été revue suite à la première preview, on a entre autre maintenant la possibilité de créer des Records locaux et d’utiliser les Sealed Classes avec les Records.
Les fonctionnalités dépréciées ou supprimées
Pas mal de dépréciation et de suppression dans cette release. Java a décidé de se passer de certaines fonctionnalités plus utilisées depuis longtemps ou qui impactent sa maintenance et c’est généralement une bonne chose.
- JEP 385: Deprecate RMI Activation for Removal. C’est une partie optionnelle de RMI, dépréciée depuis Java 8 et quasiment plus utilisée. Elle sera supprimée dans une prochaine release. Le reste de RMI reste supporté.
- JEP 381: Remove the Solaris and SPARC Ports. Une page d’histoire du rachat de Sun par Oracle se termine. Lors de ce rachat Oracle a aussi acheté un OS (Solaris) et une architecture CPU (SPARC). Ceux ci ne sont plus supportés par Java et leur implémentation dans le JVM (port) est supprimée.
- JEP 374: Disable and Deprecate Biased Locking. Biased Locking est une technique permettant d’optimiser les locks qui sont utilisés par un Thread unique. Elle ne serait plus aussi pertinente de nos jours avec les architectures CPU moderne, et entraînerait un coût de maintenance assez élevé. Elle devient désactivée par défaut et sera supprimée dans une future release.
- JEP 372: Remove the Nashorn JavaScript Engine. Nashorn a été intégré dans Java 8, déprécié en Java 11 et maintenant supprimé. Pour exécuter du JavaScript dans la JVM il faut se tourner du coté de GraalVM. Nashorn n’était plus à jour avec les nouvelles versions d’ECMAScript et son support était trop coûteux alors qu’une alternative de qualité existe avec GraalVM.
Performance
Chaque release apporte son lot d’améliorations de performance, tant en performance de pointe, qu’en temps de démarrage.
Et la release 15 a vu quelques optimisations importantes :
- G1 : Le Garbage Collector par défaut a eu plusieurs améliorations dans cette release, la plus intéressante est celle décrite dans l’article de Stefan Johansson Improving G1 out-of-the-box performance qui permet un meilleur calcul de la taille des régions de la heap, spécialement quand le Xmx et le Xms sont pas les mêmes.
- ZIP lookup : Lors du démarrage d’une JVM, celle-ci va rechercher (lookup) les entrées (classes, ressources) dans les JARs (qui sont des ZIP), des améliorations importantes ont été réalisées par une suite de patchs qui mène à un gain non négligeable pour la lecture de ces entrées. Les détails sont sur le blog de Claes Redestad Zip lookups – a word from the sponsor
- StringConcat : Les concaténations de String sont optimisées depuis Java 9 via une StringConcatFactory. Celle-ci a été refactorée pour prendre moins de temps à démarrer ainsi qu’optimiser pour les cas de concaténations les plus classiques.
- AppCDS : Application Class Data Sharing est une fonctionnalité qui permet de créer une archive de metadata de classe pour charger au démarrage d’une JVM, cela permet d’éviter de chercher sur le disque, lire et parser une classe (petite description d’AppCDS ici). Avec Java 15, les metadatas des lambdas sont ajoutées à l’archive.