SlideShare une entreprise Scribd logo
1
Les nouveautés de Java 22
@jmdoudoux
JMdoudouX
15 mai 2024
Sciam
Java SE en 2024
2
Java poursuit son évolution
En respectant le rythme de releases tous les 6 mois
Java 21 le 19 septembre 2023
JDK 21 est une version LTS
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
Java 22 a été diffusé, le 19 mars 2024
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)
Sciam 4
Jean-Michel Doudoux
Co-fondateur du
Auteur d’un didacticiel depuis 2001
Diffusé sous licence GNU FDL
• Développons en Java (4200 pages)
Directeur technique
chez
https://www.jmdoudoux.fr
@jmdoudoux
Sciam
Roadmap
Les fonctionnalités
du projet Amber
5
Les évolutions
du projet Loom
dans la JVM Hotspot
dans les API Java Core
du projet Panama
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)
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, _, _)) {
System.out.println("Employe : " + nom);
}
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
Sciam
Unnamed Variables & Patterns
Unnamed pattern variable :
Utilisable avec tous types de patterns pour déclarer sa variable
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 Personne(var nom, var _, var _)) {
System.out.println("Personne : " + nom);
}
Utilisable plusieurs fois dans la même portée
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
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
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
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
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);
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}"
}""";
Sciam
String Templates (prochaine Preview)
Dans une JEP sur une fonctionnalité en preview
Il est prévu qu’elle puisse évoluer (voire même être supprimée)
15
C’est le cas avec les String Tempates
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
… en Java 24
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
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");
}
}
1) 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)
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
2) 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
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 ( avec 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
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 une section dénommée prologue :
Impossible d’utiliser this.xxx ou super.xxx explicitement ou implicitement
Possibilité de référencer un champ d’une classe englobante ClasseEnglobante.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)
Sciam
Les fonctionnalités du
projet Loom
Structured Concurrency (Second Preview)
Scoped Values (Second Preview)
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 oeuvre
Sciam
Structured Concurrency (preview)
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
Sciam
Structured Concurrency (preview)
La mise en œuvre en plusieurs étapes
24
 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;
}
 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;
}
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;
}
 Exploiter les résultats obtenus dans des instances de type Subtask
Sciam
Structured Concurrency (preview)
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
Sciam
Structured Concurrency (preview)
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
Sciam
Structured Concurrency (preview)
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 -> {}
}
}
Sciam
Structured Concurrency (preview)
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);
}
}
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
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);
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
});
Sciam
Les fonctionnalités
du projet Panama
Foreign Function & Memory API
Vector API (Seventh Incubator)
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
Pour les détails sur cette nouvelle API
Suivez la présentation de Brice Dutheil à 14H
Brice
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
34
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)
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;
}
35
API plutôt de bas niveau, verbeuse, dépendant pour partie 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)
Sciam
Les évolutions
dans les API de Java Core
Stream Gatherers (Preview)
Class-File API (Preview)
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, …
37
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
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
Pour les détails sur cette nouvelle API
Suivez la présentation de Rémi Forax à 15H
Rémi
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, …
38
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
Sciam
Class-File API (Preview)
API riche pour permettre un accès random ou séquentiel
39
La génération utilise des builders fournis en paramètre de Lambda
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
Sciam
Class-File API (Preview)
La génération de fichiers de classe
40
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:java> 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;
}
}
Sciam
Class-File API (Preview)
La lecture et l’analyse des fichiers de classe
Avec plusieurs formes de parcours proposées
41
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>
Sciam
Class-File API (Preview)
Parcours des éléments avec un Stream
42
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));
Sciam
Class-File API (Preview)
La transformation de fichiers de classe
43
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()
Sciam
Class-File API (Preview)
Une transformation peut être considérée comme une « flatMap »
Sur la séquence d'éléments
44
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"));
Sciam
Class-File API (Preview)
Combinaison de transformations
45
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
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
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)
46
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
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
47
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
Sciam
Les évolutions
dans la JVM HotSpot
Launch Multi-File Source-Code Programs
Region Pinning for G1
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
49
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
Sciam
Launch Multi-File Source-Code Programs
But : permettre l’exécution de code dans plusieurs fichiers source
50
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
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 dîte critique
Ces objets ne doivent pas être déplacés par le GC
51
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
Sciam
Les événements JFR
Plusieurs événements Java Flight Recorder (JFR) dans la JVM HotSpot
52
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
NativeLibraryLoad ( JDK-8313251 )
Informations sur une opération de chargement
D’une bibliothèque dynamique ou une image native
NativeLibraryUnLoad ( JDK-8314211)
Informations sur une opération de déchargement
D’une bibliothèque dynamique ou une image native
Sciam
Conclusion
Sciam
Conclusion
Java poursuit son évolution en respectant son modèle de releases
La syntaxe (Amber)
54
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
Pour tester et utiliser ses fonctionnalités
L’API Stream Gatherers en preview
Sciam
Merci pour votre attention
Sciam

Contenu connexe

Similaire à Les nouveautés de Java 22 - Oracle Dev Day mai 2024.pdf

Les nouveautés de Java 21 - Devoxx MA 2023.pdf
Les nouveautés de Java 21 - Devoxx MA 2023.pdfLes nouveautés de Java 21 - Devoxx MA 2023.pdf
Les nouveautés de Java 21 - Devoxx MA 2023.pdf
Jean-Michel Doudoux
 
Améliorations dans Java depuis la version 5
Améliorations dans Java depuis la version 5Améliorations dans Java depuis la version 5
Améliorations dans Java depuis la version 5
Mamadou Oury Ba
 
Présentation nouveauté java7
Présentation nouveauté java7Présentation nouveauté java7
Présentation nouveauté java7
Cynapsys It Hotspot
 
Java 5, un blian
Java 5, un blianJava 5, un blian
Java 5, un blian
tareq
 
Java 5, un bilan
Java 5,  un bilanJava 5,  un bilan
Java 5, un bilan
teejug
 
Introduction java
Introduction javaIntroduction java
Introduction java
Fouad Root
 
Cours java smi 2007 2008
Cours java smi 2007 2008Cours java smi 2007 2008
Cours java smi 2007 2008Khalil Lechheb
 
Cours java smi 2007 2008
Cours java smi 2007 2008Cours java smi 2007 2008
Cours java smi 2007 2008Khalil Lechheb
 
Cours de C++, en français, 2002 - Cours 3.4
Cours de C++, en français, 2002 - Cours 3.4Cours de C++, en français, 2002 - Cours 3.4
Cours de C++, en français, 2002 - Cours 3.4
Laurent BUNIET
 
Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017
Jean-Michel Doudoux
 
Introspection reflection
Introspection reflectionIntrospection reflection
Introspection reflectionEric Toguem
 
L’environnement de programmation fonctionnelle DrRacket
L’environnement de programmation fonctionnelle DrRacketL’environnement de programmation fonctionnelle DrRacket
L’environnement de programmation fonctionnelle DrRacket
Stéphane Legrand
 
Java 8 - interfaces
Java 8 - interfacesJava 8 - interfaces
Java 8 - interfaces
Franck SIMON
 
Visual Studio 2008 Overview
Visual Studio 2008 OverviewVisual Studio 2008 Overview
Visual Studio 2008 OverviewGregory Renard
 
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
Paris Salesforce Developer Group
 
Change mind about JS
Change mind about JSChange mind about JS
Change mind about JS
Damien Simonin Feugas
 
201303 - Java8
201303 - Java8201303 - Java8
201303 - Java8lyonjug
 
Javascript Json artchitecture
Javascript  Json artchitecture Javascript  Json artchitecture
Javascript Json artchitecture
zaghir
 
Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016
Jean-Michel Doudoux
 

Similaire à Les nouveautés de Java 22 - Oracle Dev Day mai 2024.pdf (20)

Les nouveautés de Java 21 - Devoxx MA 2023.pdf
Les nouveautés de Java 21 - Devoxx MA 2023.pdfLes nouveautés de Java 21 - Devoxx MA 2023.pdf
Les nouveautés de Java 21 - Devoxx MA 2023.pdf
 
Améliorations dans Java depuis la version 5
Améliorations dans Java depuis la version 5Améliorations dans Java depuis la version 5
Améliorations dans Java depuis la version 5
 
Présentation nouveauté java7
Présentation nouveauté java7Présentation nouveauté java7
Présentation nouveauté java7
 
Java 5, un blian
Java 5, un blianJava 5, un blian
Java 5, un blian
 
Java 5, un bilan
Java 5,  un bilanJava 5,  un bilan
Java 5, un bilan
 
Introduction java
Introduction javaIntroduction java
Introduction java
 
Cours java smi 2007 2008
Cours java smi 2007 2008Cours java smi 2007 2008
Cours java smi 2007 2008
 
Cours java smi 2007 2008
Cours java smi 2007 2008Cours java smi 2007 2008
Cours java smi 2007 2008
 
Jdbc
JdbcJdbc
Jdbc
 
Cours de C++, en français, 2002 - Cours 3.4
Cours de C++, en français, 2002 - Cours 3.4Cours de C++, en français, 2002 - Cours 3.4
Cours de C++, en français, 2002 - Cours 3.4
 
Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017
 
Introspection reflection
Introspection reflectionIntrospection reflection
Introspection reflection
 
L’environnement de programmation fonctionnelle DrRacket
L’environnement de programmation fonctionnelle DrRacketL’environnement de programmation fonctionnelle DrRacket
L’environnement de programmation fonctionnelle DrRacket
 
Java 8 - interfaces
Java 8 - interfacesJava 8 - interfaces
Java 8 - interfaces
 
Visual Studio 2008 Overview
Visual Studio 2008 OverviewVisual Studio 2008 Overview
Visual Studio 2008 Overview
 
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
 
Change mind about JS
Change mind about JSChange mind about JS
Change mind about JS
 
201303 - Java8
201303 - Java8201303 - Java8
201303 - Java8
 
Javascript Json artchitecture
Javascript  Json artchitecture Javascript  Json artchitecture
Javascript Json artchitecture
 
Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016
 

Plus de Jean-Michel Doudoux

Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Javaday Paris 2022 - Java en 2022 : profiter de Java 17Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Jean-Michel Doudoux
 
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDK
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDKVoxxeddays Lux 2022 - Profiling et monitoring avec le JDK
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDK
Jean-Michel Doudoux
 
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdfdevoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
Jean-Michel Doudoux
 
Lyon JUG 2018 - Java le changement c'est maintenant
Lyon JUG 2018 - Java le changement c'est maintenantLyon JUG 2018 - Java le changement c'est maintenant
Lyon JUG 2018 - Java le changement c'est maintenant
Jean-Michel Doudoux
 
Nantes jug 2018 - Java le changement c'est maintenant
Nantes jug 2018 - Java le changement c'est maintenantNantes jug 2018 - Java le changement c'est maintenant
Nantes jug 2018 - Java le changement c'est maintenant
Jean-Michel Doudoux
 
Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10
Jean-Michel Doudoux
 
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
Anniversaire Paris JUG -  Deja 10 ans - retour vers le futur avec JMXAnniversaire Paris JUG -  Deja 10 ans - retour vers le futur avec JMX
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
Jean-Michel Doudoux
 
Devoxx 2018 Après Java 8, Java 9 et 10
Devoxx 2018 Après Java 8, Java 9 et 10Devoxx 2018 Après Java 8, Java 9 et 10
Devoxx 2018 Après Java 8, Java 9 et 10
Jean-Michel Doudoux
 
Apres java 8, java 9 et 10 - BreizhCamp 2018
Apres java 8, java 9 et 10 - BreizhCamp 2018Apres java 8, java 9 et 10 - BreizhCamp 2018
Apres java 8, java 9 et 10 - BreizhCamp 2018
Jean-Michel Doudoux
 
Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8
Jean-Michel Doudoux
 
"Input/Ouput, 16 ans après" à Devoxx France 2012
"Input/Ouput, 16 ans après" à Devoxx France 2012"Input/Ouput, 16 ans après" à Devoxx France 2012
"Input/Ouput, 16 ans après" à Devoxx France 2012
Jean-Michel Doudoux
 

Plus de Jean-Michel Doudoux (11)

Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Javaday Paris 2022 - Java en 2022 : profiter de Java 17Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Javaday Paris 2022 - Java en 2022 : profiter de Java 17
 
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDK
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDKVoxxeddays Lux 2022 - Profiling et monitoring avec le JDK
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDK
 
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdfdevoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
 
Lyon JUG 2018 - Java le changement c'est maintenant
Lyon JUG 2018 - Java le changement c'est maintenantLyon JUG 2018 - Java le changement c'est maintenant
Lyon JUG 2018 - Java le changement c'est maintenant
 
Nantes jug 2018 - Java le changement c'est maintenant
Nantes jug 2018 - Java le changement c'est maintenantNantes jug 2018 - Java le changement c'est maintenant
Nantes jug 2018 - Java le changement c'est maintenant
 
Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10
 
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
Anniversaire Paris JUG -  Deja 10 ans - retour vers le futur avec JMXAnniversaire Paris JUG -  Deja 10 ans - retour vers le futur avec JMX
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
 
Devoxx 2018 Après Java 8, Java 9 et 10
Devoxx 2018 Après Java 8, Java 9 et 10Devoxx 2018 Après Java 8, Java 9 et 10
Devoxx 2018 Après Java 8, Java 9 et 10
 
Apres java 8, java 9 et 10 - BreizhCamp 2018
Apres java 8, java 9 et 10 - BreizhCamp 2018Apres java 8, java 9 et 10 - BreizhCamp 2018
Apres java 8, java 9 et 10 - BreizhCamp 2018
 
Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8
 
"Input/Ouput, 16 ans après" à Devoxx France 2012
"Input/Ouput, 16 ans après" à Devoxx France 2012"Input/Ouput, 16 ans après" à Devoxx France 2012
"Input/Ouput, 16 ans après" à Devoxx France 2012
 

Les nouveautés de Java 22 - Oracle Dev Day mai 2024.pdf

  • 1. 1 Les nouveautés de Java 22 @jmdoudoux JMdoudouX 15 mai 2024
  • 2. Sciam Java SE en 2024 2 Java poursuit son évolution En respectant le rythme de releases tous les 6 mois Java 21 le 19 septembre 2023 JDK 21 est une version LTS 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 Java 22 a été diffusé, 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)
  • 4. Sciam 4 Jean-Michel Doudoux Co-fondateur du Auteur d’un didacticiel depuis 2001 Diffusé sous licence GNU FDL • Développons en Java (4200 pages) Directeur technique chez https://www.jmdoudoux.fr @jmdoudoux
  • 5. Sciam Roadmap Les fonctionnalités du projet Amber 5 Les évolutions du projet Loom dans la JVM Hotspot dans les API Java Core du projet Panama
  • 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, _, _)) { System.out.println("Employe : " + nom); } 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
  • 8. Sciam Unnamed Variables & Patterns Unnamed pattern variable : Utilisable avec tous types de patterns pour déclarer sa variable 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 Personne(var nom, var _, var _)) { System.out.println("Personne : " + nom); } Utilisable plusieurs fois dans la même portée
  • 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 une JEP sur une fonctionnalité en preview Il est prévu qu’elle puisse évoluer (voire même être supprimée) 15 C’est le cas avec les String Tempates 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 … en Java 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"); } } 1) 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 2) 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 ( avec 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 une section dénommée prologue : Impossible d’utiliser this.xxx ou super.xxx explicitement ou implicitement Possibilité de référencer un champ d’une classe englobante ClasseEnglobante.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)
  • 21. Sciam Les fonctionnalités du projet Loom Structured Concurrency (Second Preview) Scoped Values (Second 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 oeuvre
  • 23. Sciam Structured Concurrency (preview) 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
  • 24. Sciam Structured Concurrency (preview) La mise en œuvre en plusieurs étapes 24  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; }  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; } 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; }  Exploiter les résultats obtenus dans des instances de type Subtask
  • 25. Sciam Structured Concurrency (preview) 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
  • 26. Sciam Structured Concurrency (preview) 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
  • 27. Sciam Structured Concurrency (preview) 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 -> {} } }
  • 28. Sciam Structured Concurrency (preview) 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); } }
  • 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 });
  • 32. Sciam Les fonctionnalités du projet Panama Foreign Function & Memory API Vector API (Seventh Incubator)
  • 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 Pour les détails sur cette nouvelle API Suivez la présentation de Brice Dutheil à 14H Brice
  • 34. 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 34 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)
  • 35. 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; } 35 API plutôt de bas niveau, verbeuse, dépendant pour partie 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)
  • 36. Sciam Les évolutions dans les API de Java Core Stream Gatherers (Preview) Class-File API (Preview)
  • 37. 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, … 37 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 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 Pour les détails sur cette nouvelle API Suivez la présentation de Rémi Forax à 15H Rémi
  • 38. 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, … 38 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
  • 39. Sciam Class-File API (Preview) API riche pour permettre un accès random ou séquentiel 39 La génération utilise des builders fournis en paramètre de Lambda 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
  • 40. Sciam Class-File API (Preview) La génération de fichiers de classe 40 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:java> 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; } }
  • 41. Sciam Class-File API (Preview) La lecture et l’analyse des fichiers de classe Avec plusieurs formes de parcours proposées 41 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>
  • 42. Sciam Class-File API (Preview) Parcours des éléments avec un Stream 42 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));
  • 43. Sciam Class-File API (Preview) La transformation de fichiers de classe 43 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()
  • 44. Sciam Class-File API (Preview) Une transformation peut être considérée comme une « flatMap » Sur la séquence d'éléments 44 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"));
  • 45. Sciam Class-File API (Preview) Combinaison de transformations 45 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 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
  • 46. 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) 46 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
  • 47. 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 47 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
  • 48. Sciam Les évolutions dans la JVM HotSpot Launch Multi-File Source-Code Programs Region Pinning for G1
  • 49. 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 49 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
  • 50. Sciam Launch Multi-File Source-Code Programs But : permettre l’exécution de code dans plusieurs fichiers source 50 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
  • 51. 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 dîte critique Ces objets ne doivent pas être déplacés par le GC 51 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
  • 52. Sciam Les événements JFR Plusieurs événements Java Flight Recorder (JFR) dans la JVM HotSpot 52 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 NativeLibraryLoad ( JDK-8313251 ) Informations sur une opération de chargement D’une bibliothèque dynamique ou une image native NativeLibraryUnLoad ( JDK-8314211) Informations sur une opération de déchargement D’une bibliothèque dynamique ou une image native
  • 54. Sciam Conclusion Java poursuit son évolution en respectant son modèle de releases La syntaxe (Amber) 54 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 Pour tester et utiliser ses fonctionnalités L’API Stream Gatherers en preview
  • 56. Sciam