Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 22 du JDK issues des projets d’OpenJDK :
- Amber : String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
Mais aussi des fonctionnalités dans les API de Java Core et dans la JVM HotSpot qui ne font pas l'objet de JEP.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 22 du JDK issues des projets d’OpenJDK :
- Amber : String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
Mais aussi des fonctionnalités dans les API de Java Core et dans la JVM HotSpot qui ne font pas l'objet de JEP.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Les versions 19 et 20 de Java, publiées en septembre et mars derniers, sont les 10eme et 11eme release en application du modèle de release tous les 6 mois.
En attendant la publication de Java 21, la prochaine version LTS publiée en septembre de cette année, et pour en donner quelques aperçus, cette présentation brosse une revue détaillée des nouveautés introduites dans ces nouvelles versions non-LTS de Java, issues des projets Amber, Panama et Loom d’OpenJDK ainsi que des fonctionnalités non incluses dans des JEPs.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Les versions 19 et 20 de Java, publiées en septembre et mars derniers, sont les 10eme et 11eme release en application du modèle de release tous les 6 mois.
En attendant la publication de Java 21, la prochaine version LTS publiée en septembre de cette année, et pour en donner quelques aperçus, cette présentation brosse une revue détaillée des nouveautés introduites dans ces nouvelles versions de Java, issues des projets Amber, Panama et Loom d’OpenJDK ainsi que des fonctionnalités non incluses dans des JEPs.
En attendant la publication de Java 21, la prochaine version diffusée en septembre de cette année, et pour en donner quelques aperçus, cette présentation brosse une revue détaillée des nouveautés qui devraient être proposées dans cette future version LTS de Java, issues des projets Amber, Loom et Panama d’OpenJDK.
Les nouveautés de Java 21 - Rencontres dev Toulon octobre 2023.pdfJean-Michel Doudoux
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 22 du JDK issues des projets d’OpenJDK :
- Amber : String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
Mais aussi des fonctionnalités dans les API de Java Core et dans la JVM HotSpot qui ne font pas l'objet de JEP.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Les versions 19 et 20 de Java, publiées en septembre et mars derniers, sont les 10eme et 11eme release en application du modèle de release tous les 6 mois.
En attendant la publication de Java 21, la prochaine version LTS publiée en septembre de cette année, et pour en donner quelques aperçus, cette présentation brosse une revue détaillée des nouveautés introduites dans ces nouvelles versions non-LTS de Java, issues des projets Amber, Panama et Loom d’OpenJDK ainsi que des fonctionnalités non incluses dans des JEPs.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Les versions 19 et 20 de Java, publiées en septembre et mars derniers, sont les 10eme et 11eme release en application du modèle de release tous les 6 mois.
En attendant la publication de Java 21, la prochaine version LTS publiée en septembre de cette année, et pour en donner quelques aperçus, cette présentation brosse une revue détaillée des nouveautés introduites dans ces nouvelles versions de Java, issues des projets Amber, Panama et Loom d’OpenJDK ainsi que des fonctionnalités non incluses dans des JEPs.
En attendant la publication de Java 21, la prochaine version diffusée en septembre de cette année, et pour en donner quelques aperçus, cette présentation brosse une revue détaillée des nouveautés qui devraient être proposées dans cette future version LTS de Java, issues des projets Amber, Loom et Panama d’OpenJDK.
Les nouveautés de Java 21 - Rencontres dev Toulon octobre 2023.pdfJean-Michel Doudoux
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Clairement dans cette version, nous assistons à une volonté de simplification. Plus de lisibilité du code, plus d’outils pour ne plus avoir à perdre de temps sur des opérations simples et courantes, pour au final un code de meilleur qualité et plus accessible. La plupart de ces améliorations se trouvent dans cette présentation.
Le sujet principal de Java 9 est le support de la modularité mais Java 9 propose aussi de nombreuses autres fonctionnalités. Ce talk a pour but de faire une revue des principales d’entre-elles en attendant la sortie de Java 9 : support de standards, nouvelles API, évolutions dans certaines API, mises à jour des outils du JDK et améliorations de la JVM.
Durant cette session, on va vous montrer les différentes fonctions de la Tooling API avec des cas d'utilisations concrets.
Et vous présentera quelques requêtes SOQL en Tooling API utilisable au quotidien ( Dev ou Admin)
Java SE 8 est sûrement la version la plus importante et la plus impactante pour les développeurs. Deux ans après sa sortie, ce talk propose des retours sur les bonnes ou moins bonnes utilisations des principales fonctionnalités de Java 8. Une connaissance de ces fonctionnalités est requise.
Présentation des nouveautés apportées par la version 7 du langage C# : Méthodes locales, Tuples, Déconstructeurs, Pattern matching, Variables de sortie, Membres sous forme d’expression, Amélioration de la levée des exceptions, ...
Beaucoup d’applications utilisent encore Java 8 mais Java a beaucoup évolué depuis notamment avec la diffusion de deux versions LTS.
L’objectif de ce talk est de revenir sur certaines de ces nombreuses évolutions de Java, notamment récentes afin d’en profiter dans nos applications. Au-delà des évolutions syntaxiques et dans les API, ce sera aussi l’occasion de justifier la migration vers des versions plus récentes de Java.
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDKJean-Michel Doudoux
Java Flight Recorder (JFR) est une fonctionnalité de la JVM qui après activation enregistre des événements émis par son activité mais aussi celle de l’application et même du système d’exploitation avec un très faible overhead. Il est possible d’émettre ses propres événements et même de consommer des événements grâce à une API de Java 14. Depuis Java 11, JFR est open source et il est donc utilisable maintenant en production sans licence commerciale. L’exploitation de ces événements avec l’outil JMC peut être particulièrement appréciable lors d’activité de profiling et de monitoring. Cette session sera l’occasion de faire un tour d’horizon de ces fonctionnalités qui peuvent s’avérer utiles pour certaines problématiques.
Contenu connexe
Similaire à Les nouveautés de Java 22 - Lorraine JUG avril 2024.pdf
Cette présentation brosse une revue détaillée des nouveautés qui sont proposées en standard, en preview et en incubation dans la version 21 LTS du JDK issues des projets d’OpenJDK :
- Amber : Record Patterns, Pattern Matching for switch, String Templates, Unnamed Patterns and Variables, Unnamed Classes and Instance Main Methods
- Loom : Virtual Threads, Structured Concurrency, Scoped Values
- et Panama : Foreign Function & Memory API, Vector API
mais aussi de fonctionnalités dans les API de Java Core qui ne font pas l'objet de JEP et dans la JVM HotSpot.
Clairement dans cette version, nous assistons à une volonté de simplification. Plus de lisibilité du code, plus d’outils pour ne plus avoir à perdre de temps sur des opérations simples et courantes, pour au final un code de meilleur qualité et plus accessible. La plupart de ces améliorations se trouvent dans cette présentation.
Le sujet principal de Java 9 est le support de la modularité mais Java 9 propose aussi de nombreuses autres fonctionnalités. Ce talk a pour but de faire une revue des principales d’entre-elles en attendant la sortie de Java 9 : support de standards, nouvelles API, évolutions dans certaines API, mises à jour des outils du JDK et améliorations de la JVM.
Durant cette session, on va vous montrer les différentes fonctions de la Tooling API avec des cas d'utilisations concrets.
Et vous présentera quelques requêtes SOQL en Tooling API utilisable au quotidien ( Dev ou Admin)
Java SE 8 est sûrement la version la plus importante et la plus impactante pour les développeurs. Deux ans après sa sortie, ce talk propose des retours sur les bonnes ou moins bonnes utilisations des principales fonctionnalités de Java 8. Une connaissance de ces fonctionnalités est requise.
Présentation des nouveautés apportées par la version 7 du langage C# : Méthodes locales, Tuples, Déconstructeurs, Pattern matching, Variables de sortie, Membres sous forme d’expression, Amélioration de la levée des exceptions, ...
Beaucoup d’applications utilisent encore Java 8 mais Java a beaucoup évolué depuis notamment avec la diffusion de deux versions LTS.
L’objectif de ce talk est de revenir sur certaines de ces nombreuses évolutions de Java, notamment récentes afin d’en profiter dans nos applications. Au-delà des évolutions syntaxiques et dans les API, ce sera aussi l’occasion de justifier la migration vers des versions plus récentes de Java.
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDKJean-Michel Doudoux
Java Flight Recorder (JFR) est une fonctionnalité de la JVM qui après activation enregistre des événements émis par son activité mais aussi celle de l’application et même du système d’exploitation avec un très faible overhead. Il est possible d’émettre ses propres événements et même de consommer des événements grâce à une API de Java 14. Depuis Java 11, JFR est open source et il est donc utilisable maintenant en production sans licence commerciale. L’exploitation de ces événements avec l’outil JMC peut être particulièrement appréciable lors d’activité de profiling et de monitoring. Cette session sera l’occasion de faire un tour d’horizon de ces fonctionnalités qui peuvent s’avérer utiles pour certaines problématiques.
Au cours des 10 précédentes années, nous avons eu des sessions de Devoxx FR et plusieurs versions dont certaines majeures de Java.
L’objectif de ce talk est de revenir rétrospectivement sur certaines annonces et sur certaines des nombreuses évolutions de Java, notamment récentes afin d’en profiter dans nos applications. Au-delà des évolutions syntaxiques et dans les API, ce sera aussi l’occasion de justifier la migration vers des versions plus récentes de Java.
Ce n'est pas qu'un slogan politique mais bien la réalité pour Java depuis l'année écoulée.
A tel point que plusieurs caractéristiques historiques de Java sont partiellement remises en cause notamment la lenteur patente entre deux releases, l'embonpoint endémique du JRE/JDK, et même la sacro sainte rétro-compatibilité, ... Faisons un tour de ces évolutions qui sont parfois de profonds changements.
Ce n'est pas qu'un slogan politique mais bien la réalité pour Java depuis l'année écoulée.
A tel point que plusieurs caractéristiques historiques de Java sont partiellement remises en cause notamment la lenteur patente entre deux releases, l'embonpoint endémique du JRE/JDK, et même la sacro sainte rétro-compatibilité, ...
Faisons un tour de ces évolutions qui sont parfois de profonds changements avant de fêter le 10ème anniversaire du Nantes JUG.
Les versions de Java se suivent et leurs engouements ne se ressemblent pas : la version 8 de Java est probablement celle qui a suscité le plus d’intérêts chez les développeurs. Java 9, au contraire, est la version de Java qui génère le plus de craintes et d’interrogations voir de peurs. Il faut se préparer pour utiliser Java 9 d’autant que Java 10 est déjà là et les versions suivantes vont s’enchaîner. Le but de ce talk est de parcourir les avantages et les intérêts à utiliser ces nouvelles versions mais aussi certaines difficultés possibles lors de la migration.
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMXJean-Michel Doudoux
Présentation lors du dixième anniversaire du Paris JUG.
Le but est de profiter de ce dixième anniversaire pour faire une rétrospective des apports de Java et du Paris JUG à la communauté durant cette décennie et esquisser leur futur.
Les versions de Java se suivent et leurs engouements ne se ressemblent pas : la version 8 de Java est probablement celle qui a suscité le plus d’intérêts chez les développeurs. Java 9, au contraire, est la version de Java qui génère le plus de craintes et d’interrogations voir de peurs. Il faut se préparer pour utiliser Java 9 d’autant que Java 10 est déjà là et les versions suivantes vont s’enchaîner. Le but de ce talk est de parcourir les avantages et les intérêts à utiliser ces nouvelles versions mais aussi certaines difficultés possibles lors de la migration.
Les versions de Java se suivent et leurs engouements ne se ressemblent pas : la version 8 de Java est probablement celle qui a suscité le plus d’intérêts chez les développeurs. Java 9, au contraire, est la version de Java qui génère le plus de craintes et d’interrogations voir de peurs. Il faut se préparer pour utiliser Java 9 d’autant que Java 10 est déjà là et les versions suivantes vont s’enchaîner. Le but de ce talk est de parcourir les avantages et les intérêts à utiliser ces nouvelles versions mais aussi certaines difficultés possibles lors de la migration.
Java SE 8 est sûrement la version la plus importante et la plus impactante pour les développeurs. Deux ans après sa sortie, ce talk propose des retours sur les bonnes ou moins bonnes utilisations des principales fonctionnalités de Java 8. Une connaissance de ces fonctionnalités est requise.
2. Sciam
Java SE en 2024
2
Java poursuit son évolution
En respectant le rythme de release tous les 6 mois
JDK 21 est la version LTS courante
Publiée le 19 septembre 2023
Depuis la réduction de 3 à 2 ans entre 2 LTS après Java 17
OpenJDK 21 est l’implémentation de référence
Des spécifications de la version 21 de Java SE
Des patchs seront disponibles
Au moins jusqu’à la prochaine version LTS
Le JDK 22 a été le 19 mars 2024
3. Sciam
Java 22
Les spécifications dans la JSR 397
3
12 JEPs
Les nouvelles fonctionnalités
En Preview
JEP 457 : Class-File API (Preview)
JEP 461 : Stream Gatherers (Preview)
JEP 447 : Statements before super(...) (Preview)
Standard
JEP 458 : Launch Multi-File Source-Code Programs
JEP 423 : Region Pinning for G1
JEP 454 : Foreign Function & Memory API
Les fonctionnalités qui sortent de preview
JEP 456 : Unnamed Variables & Patterns
Les fonctionnalités qui restent en preview ou incubation
JEP 462 : Structured Concurrency (Second Preview)
JEP 464 : Scoped Values (Second Preview)
JEP 459 : String Templates (Second Preview)
JEP 460 : Vector API (Seventh Incubator)
JEP 463 : Implicitly Declared Classes and Instance Main Methods (Second Preview)
6. Sciam
Les fonctionnalités
du projet Amber
Unnamed Variables & Patterns
String Templates (Second Preview)
Implicitly Declared Classes and Instance Main Methods (Second Preview)
Statements before super(...) (Preview)
7. Sciam
Unnamed Variables & Patterns
En preview en Java 21 (JEP 443), en standard en Java 22
7
Unnamed pattern : un pattern inconditionnel qui ne correspond à rien
Utilisable dans un pattern imbriqué à la place d'un type ou record pattern
record Grade(String code, String designation) {}
record Employe(String nom, String prenom, Grade grade) {}
Object o = new Employe("Nom1", "Prenom1", new Grade("DEV", "Développeur"));
if (o instanceof Employe(var nom, var prenom, _)) {
System.out.println("Employe : " + nom + " " + prenom);
}
En utilisant le 51eme mot clé réservé de Java : _
But : Enrichir le langage d’une syntaxe
Pour les patterns inutilisés dans les records pattern imbriqués
Et les variables inutilisées qui doivent être déclarées
3 patterns, utilisables plusieurs fois dans la même portée
8. Sciam
Unnamed Variables & Patterns
Unnamed pattern variable :
Utilisable avec tous types de patterns
8
Unnamed variable : peut être initialisée mais non utilisée dans
Une variable locale dans un bloc
Une ressource dans un try-with-resources
L'en-tête d'une boucle for et for améliorée
Une exception d'un bloc catch
Un paramètre formel d'une expression Lambda
try (var _ = ScopedContext.acquire()) {
var _ = service.traiter((_, _) -> System.out.printn("traiter"));
} catch (Throwable _) { }
if (o instanceof Employe(var nom, var _, _)) {
System.out.println("Employe : " + nom);
}
9. Sciam
Unnamed Variables & Patterns
Utile dans des switchs avec des patterns sur des types scellés
9
void traiterFormeRonde(Forme forme) {
switch(forme) {
case Cercle c -> afficher(c);
case Carre c -> {}
case Rectangle r -> {}
}
}
switch(forme) {
case Cercle c -> afficher(c);
default -> {}
}
switch(forme) {
case Cercle c -> afficher(c);
case Carre _, Rectangle _ -> {}
}
Impossible d’avoir plusieurs patterns
nommés dans un case
Risque de bug en cas d’ajout d’un type :
sealed interface Forme permits Cercle, Carre, Rectangle {}
Utilisation possible de default
préférable d’utiliser des unnamed variables
10. Sciam
String Templates (Second Preview)
Courant de devoir créer des chaînes de caractères composées
À partir d'une combinaison de textes littéraux
Et de valeurs ou d'expressions
10
Historiquement plusieurs fonctionnalités, toutes avec inconvénients
String s = x + " + " + y + " = " + (x + y);
MessageFormat mf = new MessageFormat("{0} + {1} = {2}");
String s = mf.format(x, y, x + y);
String s = String.format("%2$d + %1$d = %3$d", x, y, x + y);
String t = "%2$d + %1$d = %3$d".formatted(x, y, x + y);
String s = new StringBuilder()
.append(x)
.append(" + ")
.append(y)
.append(" = ")
.append(x + y)
.toString();
De nombreux langages proposent l'interpolation de chaînes
Comme alternative à la concaténation de chaînes
Première preview en Java 21 via la JEP 430
11. Sciam
String Templates (Second Preview)
La plupart des langages supportent l’interpolation de chaînes
Mais le résultat peut parfois engendrer des soucis indirects
Exemple : SQL ou JSON injection
11
En combinant :
- Un texte littéral avec des expressions intégrées
- Et un processeur de templates
Pour produire des chaînes de caractères construites dynamiquement
Avec la clarté de l’interpolation et un résultat plus sûr
Le but : enrichir le langage Java avec des string templates
Qui complètent les chaînes littérales et les blocs de texte
Possibilité de créer une instance de type quelconque
Avec un processeur de templates personnalisés
12. Sciam
String Templates (Second Preview)
Nouveau type d'expression dans le langage : les templates expressions
Pour effectuer une interpolation de chaîne pour créer une chaîne ou un objet
12
Syntaxiquement, ressemble à une chaîne littérale avec un préfixe :
String prenom = "Jean-Michel";
String message = STR."Bonjour {prenom}";
Une template expression est composée de trois éléments :
1) Un processeur de templates (STR)
2) Un caractère point (U+002E), celui utilisé dans les autres expressions
3) Un template ("Bonjour {prenom}")
qui contient une expression intégrée ({prenom})
Le template peut utiliser plusieurs lignes de code source
En utilisant une syntaxe similaire à celle des blocs de texte
13. Sciam
String Templates (Second Preview)
3 processeurs de templates dans le JDK
13
STR : effectue une interpolation pour créer une chaîne
int x = 10, y = 20;
String s = STR."{x} + {y} = {x + y}";
FMT : effectue une interpolation pour créer une chaîne
Il interprète les spécificateurs de format à gauche des expressions intégrées
Les spécificateurs de format sont ceux définis dans java.util.Formatter
RAW : produit un objet de type StringTemplate
String prenom = "Jean-Michel";
StringTemplate st = RAW."Bonjour {prenom}";
String message = STR.process(st);
14. Sciam
String Templates (Second Preview)
Possibilité de définir des processeurs de templates personnalisés
Pour générer des chaînes ou des objets qui peuvent être validés
14
Une instance de l'interface fonctionnelle StringTemplate.Processor
Implémenter l’unique méthode process()
Utilisation de la fabrique StringTemplate.Processor::of
Pour obtenir une instance
var JSON = StringTemplate.Processor.of((StringTemplate st) -> new JSONObject(st.interpolate()));
String nom = "Durant";
String prenom = "Pierre";
JSONObject doc = JSON."""
{
"nom": "{nom}",
"prenom": "{prenom}"
}""";
15. Sciam
String Templates (prochaine Preview)
Dans la JEP sur les fonctionnalités en preview
Il est prévu qu’elle puisse évoluer (voire même être supprimée)
En fonction des feed backs issus des previews
15
C’est le cas avec les String Templates
Une annonce est publiée sur la mailing list
Par Brian Goetz le 9 mars 2024
https://mail.openjdk.org/pipermail/amber-spec-experts/2024-March/004010.html
La fonctionnalité va profondément changer
Il va falloir attendre les détails
dans la prochaine JEP dans le JDK 23 24
16. Sciam
Implicitly Declared Classes and Instance Main
Methods (Second Preview)
16
Plutôt compliqué
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
Les buts :
Faire évoluer le langage pour simplifier les programmes simples
Et faciliter l’apprentissage des débutants avec le langage Java
Première preview dans le JDK 21 via la JEP 445
Sous le nom Unnamed Classes and Instance Main Methods (Preview)
Changement de nom de la JEP dans la seconde preview
Deux évolutions dans un fichier source
17. Sciam
Implicitly Declared Classes and Instance Main
Methods (Second Preview)
17
4 formes autorisées :
Statique ou d’instance
Avec ou sans paramètre
class HelloWorld {
void main() {
System.out.println("Hello world");
}
}
La méthode main()
Sélection de la méthode main() en 2 étapes :
Invocation d’une méthode candidate avec un paramètre String[], si existe
Sinon invocation d’une méthode candidate sans paramètres si existe sinon erreur
Pas d’ambiguïté car une méthode statique et d’instance ne peuvent pas avoir la même signature
Visibilité : public, protected, package-private (par défaut)
18. Sciam
Implicitly Declared Classes and Instance Main
Methods (Second Preview)
18
void main() {
System.out.println("Hello world");
}
Requière un constructeur par défaut
Créé à la compilation
Aucun autre constructeur possible
Déclaration implicite d’une classe dans le package par défaut
Dont il n’est pas possible de faire référence
Car son nom est déterminé à la compilation
Peut avoir des membres
Pas de référence de méthodes statiques
static String WORLD = "world";
void main() {
System.out.print("Hello");
Util.afficher(" "+WORLD);
}
class Util {
static void afficher(String message) {
System.out.println(message);
}
}
Le nom du fichier source est libre
Pas de Javadoc
19. Sciam
Statements before super(...) (Preview)
Historiquement la première instruction d’un constructeur
Est obligatoirement l’invocation d’un constructeur de la classe ou super-classe
Explicitement (this() ou super()) ou implicitement par le compilateur
19
Afin de garantir l’initialisation des champs
Requérant des solutions
Peu élégantes
public class MonEntierPositif extends MonEntier {
public MonEntierPositif(long valeur) {
super(valeur);
if (valeur < 0) throw new IllegalArgumentException("La valeur non positive");
}
}
public MonEntierPositif(long valeur) {
super(verifier(valeur));
}
private static long verifier(long valeur) {
if (valeur < 0) throw new IllegalArgumentException("La valeur non positive");
return valeur;
}
Parfois contraignant
20. Sciam
But : permettre d’avoir dans les constructeurs des traitements
Qui ne font pas référence à l'instance avant l'invocation explicite du constructeur
20
Dans ce prologue :
Impossible d’utiliser this.xxx ou super.xxx explicite ou implicite
Impossible de référencer un champ d’une classe englobante C.this.xxx
public class MonEntierPositif extends MonEntier {
public MonEntierPositif(long valeur) {
if (valeur < 0) throw new IllegalArgumentException("La valeur non positive");
super(valeur);
}
}
Statements before super(...) (Preview)
22. Sciam
Structured Concurrency (Second Preview)
Propose un nouveau modèle de programmation
Grâce au traitement de plusieurs tâches
Exécutées dans différents threads virtuels comme une seule unité de travail
22
Fork/Join et concurrence structurée sont complémentaires
Le but : simplifier la programmation multithread
En rationalisant la gestion des erreurs et l'annulation,
En améliorant la fiabilité et en renforçant l'observabilité
Fork/Join
Conçu pour traiter des tâches à forte intensité
de calcul sur une courte durée
Utilise des threads de l’OS
Complexe à mettre œuvre
Concurrence structurée
Conçue pour traiter des tâches à forte intensité
d'E/S
Utilise des threads virtuels
Facile à mettre en œuvre
23. Sciam
API en incubation en Java 20
Classe principale : java.util.concurrent.StructuredTaskScope
23
Le modèle permet une écriture du code dans un style synchrone
Avec une exécution en asynchrone
Le code est ainsi facile à écrire, à lire et à tester
API en preview en Java 21
Dans le package java.util.concurrent
Second preview en Java 22 sans modification
Structured Concurrency (Second Preview)
24. Sciam
Facture getFacture(String codeClient, long idCommande) throws ExecutionException, InterruptedException, TimeoutException {
Facture resultat = null;
return resultat;
}
Créer une instance dans un try-with-resource
Facture getFacture(String codeClient, long idCommande) throws ExecutionException, InterruptedException, TimeoutException {
Facture resultat = null;
try (var scope = new StructuredTaskScope()) {
}
return resultat;
}
La mise en œuvre en plusieurs étapes
24
Structured Concurrency (Second Preview)
Invoquer la méthode fork() pour chaque sous-tâche à exécuter
Facture getFacture(String codeClient, long idCommande) throws ExecutionException, InterruptedException, TimeoutException {
Facture resultat = null;
try (var scope = new StructuredTaskScope()) {
Subtask<Client> clientFuture = scope.fork(() -> this.getClient(codeClient));
Subtask<Commande> commandeFuture = scope.fork(() -> this.getCommande(idCommande));
}
return resultat;
}
Attendre la fin de l’exécution des sous-tâches
• Soit sans timeout en utilisant la méthode join()
• Soit avec timeout en utilisant la méthode joinUntil()
Facture getFacture(String codeClient, long idCommande) throws ExecutionException, InterruptedException, TimeoutException {
Facture resultat = null;
try (var scope = new StructuredTaskScope()) {
Subtask<Client> clientFuture = scope.fork(() -> this.getClient(codeClient));
Subtask<Commande> commandeFuture = scope.fork(() -> this.getCommande(idCommande));
scope.joinUntil(Instant.now().plusSeconds(15));
}
return resultat;
}
Exploiter les résultats obtenus dans des instances de type Subtask
Facture getFacture(String codeClient, long idCommande) throws ExecutionException, InterruptedException, TimeoutException {
Facture resultat = null;
try (var scope = new StructuredTaskScope()) {
Subtask<Client> clientFuture = scope.fork(() -> this.getClient(codeClient));
Subtask<Commande> commandeFuture = scope.fork(() -> this.getCommande(idCommande));
scope.joinUntil(Instant.now().plusSeconds(15));
resultat = this.genererFacture(clientFuture.get(), commandeFuture.get());
}
return resultat;
}
25. Sciam
La classe StructuredTaskScope.ShutdownOnFailure
Propose un modèle invoke all
25
Facture getFacture(String codeClient, long idCommande)
throws ExecutionException, InterruptedException, TimeoutException {
Facture resultat = null;
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Subtask <Client> clientFuture = scope.fork(() -> this.getClient(codeClient));
Subtask<Commande> commandeFuture = scope.fork(() -> this.getCommande(idCommande));
scope.joinUntil(Instant.now().plusSeconds(15));
scope.throwIfFailed();
resultat = this.genererFacture(clientFuture.get(), commandeFuture.get());
}
return resultat;
}
Qui exécute toutes les sous-tâches
Et termine toutes les sous-tâches en cours si une sous-tâche lève une exception
Structured Concurrency (Second Preview)
26. Sciam
La classe StructuredTaskScope.ShutdownOnSuccess
Propose un modèle invoke any
26
Temperature getTemperature(String ville) throws InterruptedException, ExecutionException {
Temperature resultat = null;
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<Temperature>()) {
serviceMeteos.forEach(f -> {
scope.fork(() -> f.getTemperature(ville));
}
);
scope.join();
resultat = scope.result();
}
return resultat;
}
Qui renvoie le résultat de la première sous-tâche terminée
Et termine les autres sous-tâches restantes
Structured Concurrency (Second Preview)
27. Sciam
Possibilité de créer son propre scope
En héritant de la classe StructuredTaskScope
Et en y implémentant ses propres règles métiers
27
class ComposantLePlusLegerScope extends StructuredTaskScope<Composant> {
private final Collection<Composant> composants = new ConcurrentLinkedQueue<>();
private final Collection<Throwable> exceptions = new ConcurrentLinkedQueue<>();
@Override
protected void handleComplete(Subtask<? extends Composant> subtask) {
switch (subtask.state()) {
case SUCCESS -> this.composants.add(subtask.get());
case FAILED -> this.exceptions.add(subtask.exception());
case UNAVAILABLE -> {}
}
}
Structured Concurrency (Second Preview)
28. Sciam 28
public Exception exceptions() {
RuntimeException exception = new RuntimeException("Impossible d'obtenir le composant le plus leger");
exceptions.forEach(exception::addSuppressed);
return exception;
}
public Composant getComposant() throws Exception {
return composants.stream().min(Comparator.comparing(Composant::poids))
.orElseThrow(this::exceptions);
}
}
Structured Concurrency (Second Preview)
29. Sciam
Scoped Values (Second Preview)
Pour partager des objets dans le code exécuté par un thread
Historiquement depuis Java 1.2, on utilise une variable de type ThreadLocal
L’API ScopedValue tente de remédier à ces inconvénients
29
Mais cela présente plusieurs risques :
Mutable, fuite de mémoire, consommation de ressources
public final static ScopedValue<String> VALEUR = ScopedValue.newInstance();
Création d’une instance généralement statique et publique
Stocker et de partager des données immuables
Pour une durée de vie limitée à des traitements du thread qui les a écrits
En incubation dans Java 20 (JEP 429)
En preview dans Java 21 (JEP 446) et Java 22 sans modification
30. Sciam
Scoped Values (Second Preview)
where() pour définir une valeur, chainable pour plusieurs valeurs
get() pour obtenir la valeur ou lève une NoSuchElementException
30
Pour exécuter une tâche dans le thread courant
System.out.println((VALEUR.isBound() ? VALEUR.get() : "non definie"));
isBound() pour savoir si une valeur est associée au thread
run() : sous la forme d’une implémentation de Runnable
ScopedValue.where(VALEUR, "test").run(() -> { afficherValeur(); });
Ou call() : sous la forme d’une implémentation de Callable
String valeur = ScopedValue.where(VALEUR, "test")
.<String>call(monService::traiter);
31. Sciam
Scoped Values (Second Preview)
Réassociation d’une valeur pour un traitement sous-jacent
Partage avec les threads virtuels d’une StucturedTaskScope
31
ScopedValue.where(VALEUR, "valeur", () -> {
try (var scope = new StructuredTaskScope<String>()) {
afficherValeur();
scope.fork(monServiceA::traiter);
scope.fork(monServiceB::traiter);
scope.joinUntil(Instant.now().plusSeconds(10));
} catch (InterruptedException | TimeoutException e) {
e.printStackTrace();
}
});
ScopedValue.where(VALEUR, "valeur").run(() -> {
afficherValeur(); // valeur
ScopedValue.where(VALEUR, "autre-valeur").run(monService::traiter); // autre-valeur
afficherValeur(); // valeur
});
33. Sciam
Foreign Function & Memory API
API de bas niveau pour de manière simple, sûre et efficace :
• Accéder à des données en mémoire hors du tas (off heap memory)
• Invoquer des fonctions natives
Proposée en preview en Java 19 (JEP 424), 20 (JEP 434) et 21 (JEP 442)
Elle est dans le package java.lang.foreign du module java.base
33
Historiquement, fusion de 2 JEPs introduites en incubation :
Foreign-Memory Access API en Java 14 (JEP 370, 383, et 393)
Et Foreign Linker API en Java 16 (JEP 389)
Proposée en incubation en Java 17 (JEP 412) et Java 18 (JEP 419)
En Standard en Java 22
34. Sciam
L’API de bas niveau
2) Pour invoquer du code natif
Une alternative à l’API JNI présente depuis Java 1.1
34
1) Pour accéder à des données
En mémoire hors du tas (off heap memory)
De manière sûre et performante
Alternative à certaines fonctionnalités
De java.nio.ByteBuffer (pas performante mais sûre)
Et sun.misc.Unsafe (non standard)
Foreign Function & Memory API
Requière une bonne connaissance des mécanismes natifs
De bas niveau utilisés (adresses, segments, formats des données,…)
35. Sciam
API dans le package java.lang.foreign du module java.base
En utilisant des fonctionnalités d’Invoke Dynamique
VarHandle pour l’accès accès aux données
MethodHandle pour l’invocation de méthodes
35
Définit des classes et des interfaces permettant :
De contrôler l'allocation et la désallocation de la mémoire étrangère :
MemorySegment, SegmentAllocator, Arena
Foreign Function & Memory API
D’appeler des fonctions étrangères :
SymbolLookup, FunctionDescriptor, Linker
De manipuler et accéder à la mémoire étrangère structurée :
MemoryLayout et dérivées
Autoriser les appels natifs --enable-native-access=ALL-UNNAMED
Pour éviter un warning et dans le futur une erreur pour des raisons de sécurité
36. Sciam
Foreign Function & Memory API
Contrôle de l'allocation et la désallocation de la mémoire étrangère
36
L’interface Arena qui hérite de SegmentAllocator
Gère l’accès à la mémoire native et leur isolation dans une portée
Et s’assure que les segments alloués seront libérés et qu’il n’y a pas d’accès après libération
global arena : une seule, partagée par tous les threads,
Libération des segments à l’arrêt de la JVM
Arena arena = Arena.global();
automatic arena : gérée par le ramasse-miettes,
Utilisable par plusieurs threads,
Libération des segments lorsqu’il n’y a plus de référence
Arena arena = Arena.ofAuto();
confined arena : les segments sont libérés à la fermeture
De l’arena, utilisable que par le thread qui l’a créé
try (Arena arena = Arena.ofConfined()) { . . . }
shared arena : combine un confined arena
Avec une utilisation multi-threads
Arena arena = Arena.ofShared();
4 Arena proposées :
37. Sciam
Foreign Function & Memory API
MemorySegment décrit une zone de mémoire off heap
Arena::allocateFrom(String)
Helper qui alloue un segment pour une chaîne en UTF-8 au format C
MemorySegment chaineNative = arena.allocateFrom("Java");
Arena::allocate(MemoryLayout)
Pour allouer un segment correspondant à une structure
Arena::allocate(long)
Alloue un segment dont la taille en octets est précisée
Allocation avec surcharges de méthodes de SegmentAllocator
MemorySegment segment = arena.allocate(100);
Notamment :
37
38. Sciam
Foreign Function & Memory API
Manipulation et accès à la mémoire étrangère structurée
38
MemoryLayout définit la structure de mémoire d'un type spécifique
ValueLayout hérite de MemoryLayout
Définit la façon dont les types de base sont stockés en mémoire
try (Arena arena = Arena.ofConfined()) {
MemorySegment segment = arena.allocate(10 * 4); // allouer pour 10 entiers de type int (4 octets)
for (int i = 0 ; i < 10 ; i++) {
segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
}
}
Exemple :
ValueLayout.JAVA_LONG décrit le type Java primitif long
ValueLayout.ADDRESS décrit une adresse mémoire du matériel sous-jacent
39. Sciam
Foreign Function & Memory API
SequenceLayout hérite de MemoryLayout
Décrit un tableau d'un type spécifique décrit par un MemoryLayout
39
StructLayout hérite de MemoryLayout
Décrit une structure de types qui se suivent en mémoire
StructLayout dateStruct = MemoryLayout.structLayout(
ValueLayout.JAVA_SHORT.withName("annee"),
ValueLayout.JAVA_SHORT.withName("mois"),
ValueLayout.JAVA_SHORT.withName("jour"));
// tableau de 10 doubles Java
MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_DOUBLE);
// un tableau composé de trois tableaux de dix tableaux entiers
MemoryLayout.sequenceLayout(3, MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT));
40. Sciam
Foreign Function & Memory API
Manipulation de bas niveau d’un segment
40
SequenceLayout pointsLayout = MemoryLayout.sequenceLayout(10,
MemoryLayout.structLayout(ValueLayout.JAVA_INT.withName("x"), ValueLayout.JAVA_INT.withName("y")));
VarHandle xHandle = pointsLayout.varHandle(PathElement.sequenceElement(), PathElement.groupElement("x"));
VarHandle yHandle = pointsLayout.varHandle(PathElement.sequenceElement(), PathElement.groupElement("y"));
MemorySegment segment = arena.allocate(pointsLayout);
for (int i = 0; i < pointsLayout.elementCount(); i++) {
xHandle.set(segment, (long) i, i);
yHandle.set(segment, (long) i, i);
}
MemorySegment segment = arena.allocate((long)(2 * 4 * 10), 1);
for (int i = 0; i < 10; i++) {
segment.setAtIndex(ValueLayout.JAVA_INT, (i * 2), i); // x
segment.setAtIndex(ValueLayout.JAVA_INT, (i * 2) + 1, i); // y
}
Manipulation d’un segment structuré avec des VarHandles
41. Sciam
Foreign Function & Memory API
Recherche et description de fonctions étrangères
41
L’interface SymbolLookup
Pour localiser et rechercher l’adresse de fonctions dans les bibliothèques natives
L’interface FunctionDescriptor
Décrit les paramètres entrants et sortants d'une fonction native
Chargement optionnel de la bibliothèque native par le ClassLoader
Avec System::loadLibrary
Des fabriques pour obtenir une instance :
static SymbolLookup loaderLookup()
pour une instance sur les bibliothèques chargées par le ClassLoader
static SymbolLookup libraryLookup(String, Arena) et libraryLookup(Path, Arena)
pour une instance sur une bibliothèque qui sera chargée au besoin
Lors de l'appel de fonction native avec un MethodHandle
s'assure que les types Java transférés sont convertis en types C corrects
et que la valeur de retour est convertie d'un type C vers le type de retour Java
42. Sciam
Foreign Function & Memory API
Obtenir un éditeur de liens spécifique à l’Application Binary Interface
42
Linker
Crée un éditeur de liens spécifique à l’ABI de la plate-forme native sous-jacente
Linker linker = Linker.nativeLinker();
Une ABI est un ensemble de conventions d’appel et de types de données
Associés au compilateur, au système d’exploitation et au processeur utilisés
Optimisé pour les conventions d'appel de nombreuses plateformes :
Linux/x64 Linux/AArch64 Linux/RISC-V Linux/PPC64 Linux/s390
macOS/x64 macOS/AArch64 Windows/x64 Windows/AArch64 AIX/ppc64
Prend en charge les conventions d'appel des autres plateformes en déléguant à libffi
SymbolLookup stdlib = linker.defaultLookup();
La méthode defaultLookup() renvoie un SymbolLookup
Pour rechercher une fonction dans un ensemble de bibliothèques courantes
Exemple : libc sous Linux
43. Sciam
Foreign Function & Memory API
Appel à des fonctions étrangères via des MethodHandles
43
Linker permet une interaction aller-retour
Entre le code Java et les fonctions étrangères
MethodHandle strlen = linker.downcallHandle(
linker.defaultLookup().find("strlen").get(), FunctionDescriptor.of(JAVA_LONG, ADDRESS)
);
try (Arena arena = Arena.ofConfined()) {
MemorySegment chaine = arena.allocateFrom("Java");
long len = (long) strlen.invoke(chaine);
}
Les appels ascendants (upcall)
Appels du code natif vers le code Java
Les appels descendants (downcall)
Appels du code Java vers le code natif
44. Sciam
public class DialogFFM {
public static void main(String[] args) {
try {
System.loadLibrary("user32");
Optional<MemorySegment> msgBoxFunction = SymbolLookup.loaderLookup().find("MessageBoxA");
FunctionDescriptor msgBoxFunctionDesc = FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS, ADDRESS, JAVA_INT);
Linker linker = Linker.nativeLinker();
MethodHandle methodHandle = linker.downcallHandle(msgBoxFunction.get(), msgBoxFunctionDesc);
try (Arena offHeap = Arena.ofConfined()) {
MemorySegment cStringMessage = offHeap.allocateFrom("Voulez-vous utiliser Java 22 ?");
MemorySegment cStringTitre = offHeap.allocateFrom("Confirmation");
int bouton = (int) methodHandle.invoke(NULL, cStringMessage, cStringTitre, 36);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
44
Foreign Function & Memory API
Exemple sous Windows
45. Sciam
Vector API (Seventh Incubator)
Exprimer des calculs vectoriels
Qui, au moment de l'exécution, sont systématiquement compilés
Avec les meilleures instructions vectorielles possibles sur l’architectures CPU
Les SIMD sur les CPU supportées : x64 (SSE et AVX) et AArch64 (Neon)
Dans le module jdk.incubator.vector
45
Single Instruction, Multiple Data
Traiter en parallèle un tableau de données, sans threads
Pour appliquer une même opération sur plusieurs valeurs traitées
En un seul cycle de traitement CPU
En incubation en Java 16 (JEP 338), 17 (JEP 414), 18 (JEP 417),
19 (JEP 426), 20 (JEP 438) et 21 (JEP 448)
46. Sciam
static float[] calculerScalaire(float[] a, float[] b) {
float[] c = new float[a.length];
for (int i = 0 ; i < a.length ; i++) {
c[i] = a[i] * a[i] - b[i] * b[i];
}
return c;
}
46
API plutôt de bas niveau, verbeuse, dépendant partiellement du CPU
Mais qui peut offrir de meilleures performances que le code scalaire équivalent
Exemple Java 22
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;
static float[] calculerVectoriel(float[] a, float[] b) {
float[] c = new float[a.length];
int i = 0;
for (; i < SPECIES.loopBound(a.length) ; i += SPECIES.length()) {
var va = FloatVector.fromArray(SPECIES, a, i);
var vb = FloatVector.fromArray(SPECIES, b, i);
var vr = va.mul(va).sub(vb.mul(vb));
vr.intoArray(c, i);
}
for (; i < a.length; i++) {
c[i] = a[i] * a[i] - b[i] * b[i];
}
return c;
}
Vector API (Seventh Incubator)
48. Sciam
Stream Gatherers (Preview)
L'API Stream fournit un ensemble complet mais fixe d'opérations
Intermédiaires et terminales : filtrage, transformation, réduction, tri, …
48
Le but : proposer l’opération intermédiaire Stream::gather extensible
Qui permet d’exprimer quasiment toutes les implémentations voulues
En utilisant l’API Gatherer similaire à l’API Collector
Une opération terminale extensible Stream::collect
Qui permet de produire le résultat d'un pipeline de diverses manières
En utilisant l’API Collector
Mais ce nombre fixe d’opérations empêche d’exprimer
Certains traitements complexes
Plusieurs opérations intermédiaires ont déjà été ajoutées
Mais ce n’est pas solution maintenable dans le temps
49. Sciam
Stream Gatherers (Preview)
Attend en paramètre une implémentation de l’interface Gatherer
49
Elle définit quatre fonctions :
default BiConsumer<A,Gatherer.Downstream<? super R>> finisher()
Optionnelle, invoquée lorsqu'il n'y a plus d'éléments à traiter
Peut utiliser l'objet d'état privé
Pour éventuellement, émettre des éléments de sortie supplémentaires
Gatherer.Integrator<A,T,R> integrator()
Intègre un nouvel élément du flux d'entrée éventuellement avec l'objet d'état privé
Pour émettre éventuellement des éléments vers le flux de sortie
Peut interrompre le traitement avant d'atteindre la fin du flux d'entrée
default Supplier<A>initializer()
Fonction d'initialisation facultative fournit un objet
Qui conserve un état privé pendant le traitement des éléments du flux
default BinaryOperator<A> combiner()
Optionnelle, utilisée pour combiner les gatherers
Lorsque le flux d'entrée est marqué comme parallèle
50. Sciam
Stream Gatherers (Preview)
L’interface fonctionnelle Gatherer.Downstream<T>
50
La méthode abstraite boolean push(T element)
Pour envoyer éventuellement l’élément en sortie
Elle renvoie un booléen : false pour short cirtuiting sinon true
L’interface fonctionnelle Gatherer.Integrator<A, T, R>
Une instance est retournée par l’integrator
Une instance est fournie à l’integrator et au finisher
La méthode boolean integrate(A state, T element, Downstream<? super R> downstream)
Pour traiter un élément entrant et renvoyer un booléen (false pour short cirtuiting)
Function<Personne, String> mapper = // . . . Transforme une Personne en String
Integrator<Void, Personne, String> integrator = (state, element, downstream) -> {
R mappedElement = mapper.apply(element);
downstream.push(mappedElement);
return true;
};
51. Sciam
Stream Gatherers (Preview)
L’interface Gatherer propose aussi différentes surcharges de la fabrique of()
Pour obtenir un Gatherer
À partir de l’implémentation d’une ou plusieurs des quatre fonctions
51
Exemple : un Gatherer équivalent à l’opération map()
public static <T, R> Gatherer<T, Void, R> mapping(Function<? super T, ? super R> mapper) {
return Gatherer.of( (_ , element, downstream) -> {
R mapped = mapper.apply(element);
downstream.push(mapped);
return true;
});
}
Un Gatherer peut être :
Exécuté en séquentiel ou parallèle
Stateless ou statefull
Short-Circuiting ou greedy
52. Sciam
Stream Gatherers (Preview)
La classe Gatherers propose des fabriques pour usages courants
52
fold(Supplier<R> initial, BiFunction<? super R,? super T,? extends R> folder)
Renvoie un Gatherer qui construit un agrégat de manière incrémentielle
Et émet cet agrégat lorsqu'il n'y a plus d'éléments d'entrée
scan(Supplier<R> initial, BiFunction<? super R,? super T,? extends R> scanner)
Renvoie un Gatherer 1-1 qui applique une fonction fournie
À l'état actuel et à l'élément pour produire l'élément suivant, qu'il transmet en sortie
List<String> nombreStr = Stream.of(1, 2, 3, 4, 5)
.gather(Gatherers.fold(() -> "", (string, number) -> !string.isEmpty() ? string + ";" + number : string + number))
.toList();
System.out.println(nombreStr); // [1;2;3;4;5]
List<String> nombreStrs = Stream.of(1, 2, 3, 4, 5)
.gather(Gatherers.scan(() -> "", (string, number) -> string + number))
.toList();
System.out.println(nombreStrs); // [1, 12, 123, 1234, 12345]
53. Sciam
Stream Gatherers (Preview)
windowFixed(int windowSize)
Renvoie un Gatherer n-m qui regroupe les éléments d'entrée
Dans des listes d'une taille donnée
Et transmet les listes en sortie lorsqu'elles sont pleines
53
windowSliding(int windowSize)
Renvoie un Gatherer n-m qui regroupe les éléments d'entrée
Dans des listes d'une taille fournie
Après la première fenêtre, chaque liste suivante est créée à partir d'une copie de
La précédente en supprimant le premier élément
Et en ajoutant l'élément suivant à partir du flux d'entrée
List<List<Integer>> windowsFixed = Stream.of(1, 2, 3, 4, 5, 6, 7, 8).gather(Gatherers.windowFixed(3)).toList();
System.out.println(windowsFixed); // [[1, 2, 3], [4, 5, 6], [7, 8]]
List<List<Integer>> windowSlicing = Stream.of(1, 2, 3, 4, 5).gather(Gatherers.windowSliding(3)).toList();
System.out.println(windowSlicing); // [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
54. Sciam
Stream Gatherers (Preview)
mapConcurrent(int maxConc, Function<? super T,? extends R> mapper)
Renvoie un Gatherer 1-1 qui invoque une fonction fournie
Sur chaque élément d'entrée en parallèle, jusqu'à une limite fournie
54
55. Sciam
Stream Gatherers (Preview)
Les gatherers supportent la composition
55
via la méthode andThen(Gatherer)
Qui joint deux gatherers
Où le premier produit des éléments que le second peut consommer
Cela permet de créer des gatherers sophistiqués
En composant des gatherers plus simples
Tout comme la composition de fonctions
Ainsi sémantiquement :
source.gather(a).gather(b).gather(c).collect(...)
Est équivalent à :
source.gather(a.andThen(b).andThen(c)).collect(...)
56. Sciam
Class-File API (Preview)
L'écosystème Java dispose de plusieurs bibliothèques
Pour manipuler le bytecode
Toutes hors du JDK : ASM, BCEL, Javassist, ByteBuddy, …
56
But : fournir une API standard
Pour l'analyse, la génération et la transformation de fichier de classe Java
Le JDK utilise en interne ASM
Dans une version N-1 par rapport à la version N du JDK
Dans le package java.lang.classfile
Utilisées par de nombreux frameworks
57. Sciam
Class-File API (Preview)
API riche pour permettre un accès random ou séquentiel
57
La génération utilise des builders fournis en paramètre d’interfaces fonctionnelles
Les différents composants sont modélisés :
xxxModel représentent des structures complexes, immuables
telles que des classes, des méthodes, des champs, le corps d'une méthode
xxxElement représentent un élément du fichier de classe, immuables
Les Elements peuvent être des Models et un Model possède un Element correspondant
xxxEntry représentent les éléments du constant pool (PoolEntry, ClassEntry, Utf8Entry)
Également exposés sous la forme de Model et d’Element
Attribute représentent un attribut d’un élément
Majoritairement exposés sous la forme d’Element
API moderne
Utilisation de fabriques, de types scellés, d’immutabilité, …
Utilise les types du package java.lang.constant pour les informations symboliques
58. Sciam
Class-File API (Preview)
La génération de fichiers de classe
58
import java.lang.classfile.ClassFile;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.nio.file.Path;
import static java.lang.classfile.ClassFile.ACC_PUBLIC;
import static java.lang.classfile.ClassFile.ACC_STATIC;
import static java.lang.constant.ConstantDescs.CD_int;
import static java.lang.constant.ConstantDescs.CD_long;
public class TestClassFile {
public static void main(String[] args) throws java.io.IOException {
ClassFile.of().buildTo(Path.of("EntierUtils.class"),
ClassDesc.of("EntierUtils"),
classBuilder -> classBuilder.withMethodBody("ajouter",
MethodTypeDesc.of(CD_long, CD_int, CD_int),
ACC_PUBLIC | ACC_STATIC,
codeBuilder -> codeBuilder.iload(1)
.i2l()
.iload(2)
.i2l()
.ladd()
.lreturn()));
}
}
C:javaTestJava22> javap -c .EntierUtils.class
public class EntierUtils {
public static long ajouter(int, int);
Code:
0: iload_1
1: i2l
2: iload_2
3: i2l
4: ladd
5: lreturn
}
Equivalent à (sans constructeur par défaut)
public class EntierUtils {
public static long ajouter(int a, int b) {
return (long) a + b;
}
}
59. Sciam
Class-File API (Preview)
La lecture et l’analyse des fichiers de classe
Avec plusieurs formes de parcours proposées
59
ClassModel cm = ClassFile.of().parse(Path.of("EntierUtils.class"));
for (ClassElement ce : cm) {
switch (ce) {
case MethodModel mm -> {
System.out.printf("Methode %s%s%n", mm.methodName().stringValue(), mm.methodTypeSymbol().displayDescriptor());
for (MethodElement me : mm)
if (me instanceof CodeModel xm)
for (CodeElement el : xm)
System.out.printf(" %s%n", el);
}
default -> {}
}
}
Methode ajouter(int,int)long
Load[OP=ILOAD_1, slot=1]
UnboundConvertInstruction[op=I2L]
Load[OP=ILOAD_2, slot=2]
UnboundConvertInstruction[op=I2L]
UnboundOperatorInstruction[op=LADD]
Return[OP=LRETURN]
Débute par l’obtention d’un ClassModel
En invoquant une surcharge de ClassFile::parse
Parcours des éléments encapsulés dans un type ClassElement
Car ClassModel implémente Iterable<ClassElement>
60. Sciam
Class-File API (Preview)
Parcours des éléments avec un Stream
60
ClassModel cm = ClassFile.of().parse(Path.of("EntierUtils.class"));
for (MethodModel mm : cm.methods()) {
System.out.printf("Methode %s%s%n", mm.methodName().stringValue(), mm.methodTypeSymbol().displayDescriptor());
for (MethodElement me : mm)
if (me instanceof CodeModel xm)
for (CodeElement el : xm)
System.out.printf(" %s%n", el);
}
Parcours des éléments selon leur type
En invoquant des méthodes dédiées : fields(), methods()
ClassModel cm = ClassFile.of().parse(Path.of("EntierUtils.class"));
cm.elementStream()
.flatMap(ce -> ce instanceof MethodModel mm ? mm.elementStream() : Stream.empty())
.flatMap(me -> me instanceof CodeModel com ? com.elementStream() : Stream.empty())
.forEach(com -> System.out.printf(" %s%n", com));
61. Sciam
Class-File API (Preview)
La transformation de fichiers de classe
61
Souvent la combinaison de lecture et écriture
Où un fichier de classe est lu, des modifications localisées sont apportées,
Mais une grande partie du fichier de classe est transmise sans modification
Chaque XxxBuilder dispose d'une méthode with(XxxElement)
Qui permet d’inclure directement les éléments sans les modifier
ClassModel cm = ClassFile.of().parse(Path.of("EntierUtils.class"));
byte[] newBytes = ClassFile.of().build(cm.thisClass().asSymbol(),
classBuilder -> {
for (ClassElement ce : cm) {
if (!(ce instanceof MethodModel mm && mm.methodName().stringValue().equals("ajouter"))) {
classBuilder.with(ce);
}
}
});
Exemple : retirer la méthode ajouter()
62. Sciam
Class-File API (Preview)
Une transformation peut être considérée comme une « flatMap »
Sur la séquence d'éléments
62
ClassTransform ct = (builder, element) -> {
if (!(element instanceof MethodModel mm && mm.methodName().stringValue().equals("ajouter")))
builder.with(element);
};
var cc = ClassFile.of();
byte[] newBytes = cc.transform(cc.parse(Path.of("EntierUtils.class")), ct);
Chaque Model a un type Transform correspondant
ClassTransform::dropping helper pour retirer des éléments
ClassTransform ct = ClassTransform.dropping(
element -> element instanceof MethodModel mm && mm.methodName().stringValue().equals("ajouter"));
63. Sciam
Class-File API (Preview)
Combinaison de transformations
63
Exemple : remplacer tous les opcodes ladd par lsub
Pour faire manuellement une transformation pour du mutation testing
CodeTransform laddToLsub = (b, e) -> {
if (e instanceof Instruction i && i.opcode() == Opcode.LADD) b.lsub();
else b.with(e);
};
Définition d’un CodeTransform
MethodTransform mt = MethodTransform.transformingCode(laddToLsub);
ClassTransform ct = ClassTransform.transformingMethods(mt);
Définition d’un MethodTransform utilisant le CodeTransform et d’un ClassTransform
ClassTransform ct = ClassTransform.transformingMethodBodies(laddToLsub);
Ou plus simplement
var cc = ClassFile.of();
byte[] newBytes = ClassFile.of().transform(cc.parse(Path.of("EntierUtils.class")), ct);
Application de la transformation
64. Sciam
La classe ListFormat
Pour formater ou analyser une liste de chaîne de caractères
D’une manière sensible aux paramètres régionaux (Locale)
64
Le type de mise en forme avec l’énumération ListFormat.Type
Qui détermine la ponctuation entre les chaînes et les mots de liaison, le cas échéant
Valeurs définies : STANDARD (par défaut), OR et UNIT
var elements = List.of("E1", "E2", "E3");
System.out.println(ListFormat.getInstance().format(elements));
System.out.println(ListFormat.getInstance(Locale.FRANCE, OR, FULL).format(elements));
System.out.println(ListFormat.getInstance(Locale.US, STANDARD, FULL).format(elements));
System.out.println(ListFormat.getInstance(Locale.US, STANDARD, SHORT).format(elements));
E1, E2 et E3
E1, E2 ou E3
E1, E2, and E3
E1, E2, & E3
Une instance est obtenue avec une fabrique à qui on peut passer :
Une locale, sinon la locale par défaut sera utilisée
Le style de mise en forme avec l’énumération ListFormat.Style
Qui adapte la façon dont les chaînes sont abrégées (ou non) selon le type
Valeurs définies : FULL (par défaut), SHORT et NARROW
65. Sciam
Ajout divers dans l’API Java Core
boolean Console.isTerminal()
Retourne un booléen qui indique si l’instance de la console est un terminal
65
static class<?> Class.forPrimitiveName(String)
Retourne la classe associée au type primitif donné sinon null
Les 9 types primitifs sont boolean, byte, char, short, int, long, float, double et void
static InetAddress InetAddress.ofLiteral(String)
Créé une instance depuis la représentation textuelle de l’adresse IP
Existe aussi pour les classes Inet4Address et Inet6Address
Default DoubleStream RandomGenerator.equiDoubles(double left,
double right, boolean isLeftIncluded, boolean isRightIncluded)
Renvoie un Stream illimité de valeurs doubles choisies de manière pseudo-aléatoire,
Où chaque valeur est comprise entre la limite gauche et la limite droite spécifiées
Incluses ou non avec une garantit une distribution uniforme
67. Sciam
Launch Multi-File Source-Code Programs
Depuis le JDK 11, la JVM peut exécuter UN unique fichier .java
Sans avoir à le compiler en préalable ( JEP 330 )
Pouvant contenir plusieurs types
67
Exécuter la JVM avec le fichier .java
Une compilation en mémoire est effectuée avant l’exécution
public class Hello {
public static void main(String[] args) {
Utils.saluer();
}
interface Utils {
static void saluer() {
System.out.println("Hello");
}
}
}
C:java>java Hello.java
Hello
C:java>dir
14/02/2024 17:40 <DIR> .
16/01/2024 10:14 <DIR> ..
14/02/2024 17:40 195 Hello.java
68. Sciam
Launch Multi-File Source-Code Programs
But : permettre l’exécution de code dans plusieurs fichiers source
68
Impossible d'avoir un même type déclaré dans plusieurs fichiers source
Pas de garantie d’ordre ou de temporalité pour la compilation .java
Compilation à la volée ou lazy
Si une classe utilisée est dans le même fichier .java
Elle n’est pas recherchée et est compilée et utilisée
Seuls les .java dont les types sont utilisés par l’application sont compilés
public class Hello {
public static void main(String[] args) {
Utils.saluer();
}
}
public interface Utils {
static void saluer() {
System.out.println("Hello");
}
}
C:java>java Hello.java
Hello
C:java>dir /W
[.] [..]
Hello.java Utils.java
69. Sciam
Region Pinning for G1
JNI a besoin de définir et libérer des pointeurs sur des objets Java
Les traitements sont lors exécutés dans une section dite critique
Ces objets ne doivent pas être déplacés par le GC
69
But : Réduire la latence en permettant l'épinglage des régions par G1
Contenant un objet d’une section critique de JNI
Historiquement, G1 suspend tous ses traitements
Lors de l’exécution de régions critiques de JNI
Pouvant impliquer un risque de bloquer les threads de l’application
Voir même une OutOfMemoryError
Les régions sans section critique peuvent être traitées
Évitant de bloquer les autres threads de l’application pouvant nécessiter le GC
Améliore les performances et réduit les risques avec JNI
70. Sciam
Les événements JFR
Plusieurs événements JFR ajoutés dans la JVM HotSpot
70
CompilerQueueUtilization ( JDK-8317562 )
Statistiques des queues des compilateur du JIT
Un événement pour C1 et C2
DeprecatedInvocation ( JDK-8211238 )
Invocation unique d’une méthode annotée avec @Deprecated du JDK
NativeLibraryLoad ( JDK-8313251 ) et NativeLibraryUnLoad ( JDK-8314211)
Informations sur une opération de chargement / déchargement
D’une bibliothèque dynamique ou une image native
71. Sciam
Les autres évolutions dans les GC
Plusieurs améliorations ont été apportées dans les GC
71
G1 GC
Code root scan causes long GC pauses due to imbalanced iteration (JDK-8315503)
Fast Collection of Evacuation Failed Regions (JDK-8140326)
More Deterministic Heap Resize at Remark (JDK-8314573)
Parallel GC
amélioration du throughput avec des grands tableaux (JDK-8321013)
Precise Parallel Scanning of Large Object Arrays for Young Collection Roots (JDK-8310031)
Serial GC
Better GC Throughput with Scarce Dirty Cards (JDK-8319373)
73. Sciam
Avant le JDK 22, le compilateur javac acceptait
les références de méthode privées avec comme récepteur une variable de type
73
import java.util.function.*;
class Fonction {
private String asString() { return "test"; }
static <T extends Fonction> Function<T, String> get() {
return T::asString;
}
}
Avec le JDK 22, le compilateur javac émet une erreur
C:java>javac Fonction.java
Fonction.java:9: error: asString() has private access in Fonction
return T::asString;
^
1 error
Les évolutions dans javac
74. Sciam
Avant le JDK 22, le compilateur javac permettait
l’utilisation du mot clé final au début d’un record pattern
dans le case d’un switch utilisant du pattern matching
74
Object o = new Pays("France");
switch ( o ) {
case final Pays(var n) -> {}
default -> {}
}
Avec le JDK 22, le compilateur javac émet une erreur
C:java>javac Pays.java
Pays.java:6: error: modifier final not allowed here
case final Pays(var n) -> {}
^
1 error
Les évolutions dans javac
76. Sciam
Conclusion
Java poursuit son évolution en respectant son modèle de releases
La syntaxe (Amber)
76
Java 22 proposent des fonctionnalités concernant :
Cela permettra à Java de rester pertinent aujourd’hui et demain
La programmation parallèle et concurrente (Loom)
Une meilleure utilisation du matériel moderne (Panama) avec FFM en standard
N’hésitez pas à télécharger un JDK 22 auprès d’un fournisseur
L’API Stream Gatherers et ClassFile en preview