SlideShare una empresa de Scribd logo
1 de 61
Descargar para leer sin conexión
Devoxx France 2023
Les nouveautés
de Java 19 et 20
JMdoudouX
Sciam
Devoxx France 2023
Sciam
Java poursuit son évolution
En respectant le rythme de release tous les 6 mois
Java 19 et 20
Java 19 Java 20
Publication 20 septembre 2022 21 mars 2023
Spécification JSR 394 JSR 395
Implémentation
de référence
OpenJDK 19 OpenJDK 20
Durée des patchs 6 mois 6 mois
Nb JEPs 7 7
Devoxx France 2023
Sciam
Quelques fonctionnalités
Quasiment toutes en preview ou incubation
Les JEPs de Java version 19 et 20
Java 19 Java 20
Record Patterns 405 (Preview) 432 (Second Preview)
Foreign Function & Memory API 424 (Preview) 434 (Second Preview)
Virtual Threads 425 (Preview) 436 (Second Preview)
Pattern Matching for switch 427 (Third Preview) 433 (Fourth Preview)
Vector API 426 (Fourth Incubator) 438 (Fifth Incubator)
Structured Concurrency 428 (Incubator) 437 (Second Incubator)
Scoped Values 419 (Incubator)
Linux/RISC-V Port 422
Devoxx France 2023
Sciam
Jean-Michel Doudoux
Senior Tech Lead
chez
Auteur de 2 didacticiels
Diffusés sous licence GNU FDL
• Développons en Java (4000 pages)
• Développons en Java avec Eclipse
Co-fondateur du
https://www.jmdoudoux.fr
@jmdoudoux
Devoxx France 2023
Sciam
Roadmap
Les fonctionnalités des JEPs
du projet Amber
du projet Panama
du projet Loom
Les autres évolutions
Devoxx France 2023
Sciam
Les fonctionnalités du projet Amber
Record Patterns
Pattern Matching for switch
Devoxx France 2023
Sciam
Type pattern utilisable avec le pattern matching sur les records
Record Patterns (Preview)
Ajouter un nouveau pattern utilisable dans le pattern matching
Le record pattern pour déconstruire les valeurs d’un record
record Employe(String nom, String prenom) {}
Object o = new Employe("Nom1", "Prenom1");
if (o instanceof Employe emp) {
System.out.println("Employe : "+emp.nom()+" "+emp.prenom());
}
if (o instanceof Employe(String nom, String prenom)) {
System.out.println("Employe : "+nom+" "+prenom);
}
En preview en Java 19 (JEP 420) et 20 (JEP 432)
Devoxx France 2023
Sciam
Java 19 : utilisable avec une instruction instanceof ou switch
Record Patterns (Preview)
Java 20 : utilisable dans une boucle for améliorée
Type pattern et record pattern peuvent être combinés
Dans un même switch
switch (o) {
case Employe emp -> System.out.println(emp);
case Grade(String code, String designation) -> System.out.println("Grade " + designation + "(" + code + ")");
default -> System.out.println("Type non supporté");
}
List<Employe> employes = List.of(new Employe("Nom1", "Prenom1"));
for(Employe(var nom, var prenom) : employes) {
System.out.println(nom + " " + prenom);
}
Un élément null lève une java.lang.MatchException
Devoxx France 2023
Sciam
Le nom des composants peut être différents
Seuls l’ordre et le type des composants doivent être respectés
Record Patterns (Preview)
Utilisation possible de l’inférence du type dans le pattern
if (o instanceof Employe(String n, String p)) {
System.out.println("Employe : " + n + " " + p);
}
if (o instanceof Employe(var nom, var prenom)) {
System.out.println("Employe : "+nom+" "+prenom);
}
Devoxx France 2023
Sciam
Java 19
Record Patterns (Preview)
if (o instanceof Employe(var nom, var prenom) emp) {
System.out.println("Employe : " + nom + " " + prenom + " {" + emp + "}" );
}
Possibilité de définir une variable qui permet d’accéder à l’instance
Record pattern nommé (named record pattern)
Java 20 : fonctionnalité retirée
Devoxx France 2023
Sciam
Les record patterns peuvent être imbriqués
Record Patterns (Preview)
La valeur null ne correspond à aucun 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, Grade(var code, var designation))) {
System.out.println("Employe : " + nom + " " + prenom + ", "+ designation);
}
Devoxx France 2023
Sciam
Avec un record générique
Record Patterns (Preview)
Java 20 : support de l'inférence des types d’arguments génériques
Java 19 : pas de déconstruction d’un type brut
if (monoDeMono instanceof Mono<Mono<String>>(Mono<String>(var s))) {
System.out.println("mono contient " + s);
}
if (monoDeMono instanceof Mono(Mono(var s))) {
System.out.println("mono contient " + s);
}
record Mono<T>(T val) implements Container<T> {}
Mono<Mono<String>> monoDeMono = new Mono<>(new Mono<>("valeur"));
Devoxx France 2023
Sciam
Historiquement en preview en Java
17 (JEP 406), 18 (JEP 420), 19 (JEP 427) et 20 (JEP 433)
Pattern Matching for switch (Preview)
Utiliser le pattern matching dans une instruction switch
Avec support de la valeur null contrairement à la levée historique d’une NPE
Exemple en Java 18
static String getDesignation(Object obj) {
String designation = switch (obj) {
case Terrain t
&& (t.getSurface() > 1000) -> "Grand terrain";
case Terrain t -> "Petit terrain";
case null -> "Instance null";
default -> "Pas un terrain";
};
return designation;
}
Devoxx France 2023
Sciam
Java 19 : troisième preview apporte deux évolutions
Pattern Matching for switch (Preview)
Le guarded pattern utilise le nouveau mot clé contextuel when
À la place de l’opérateur && dans les précédentes preview
static String getDesignation(Object obj) {
String designation = switch (obj) {
case Terrain t
when (t.getSurface() > 1000) -> "Grand terrain";
case Terrain t -> "Petit terrain";
case null -> "Instance null";
default -> "Pas un terrain";
};
return designation;
}
Devoxx France 2023
Sciam
Sémantique d'exécution d’un switch avec le pattern matching
Lorsque la valeur est null et que le cas null n’est pas explicitement géré :
Elle est plus étroitement alignée sur la sémantique historique des switchs
Pattern Matching for switch (Preview)
public static void main(String[] args) {
String chaine = null;
switch (chaine) {
case String s -> {
System.out.println("traitement chaine");
System.out.println("taille : " + s.length());
}
}
}
Devoxx France 2023
Sciam
Java 18
Pattern Matching for switch (Preview)
C:java>javac --enable-preview --release 18 -g TestSwitchPattern.java
Note: TestSwitchPattern.java uses preview features of Java SE 18.
C:java>java --enable-preview TestSwitchPattern
traitement chaine
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "s" is null
at TestSwitchPattern.main(TestSwitchPattern.java:8)
Java 19
C:java>javac --enable-preview --release 19 TestSwitchPattern.java
Note: TestSwitchPattern.java uses preview features of Java SE 19.
C:java>java --enable-preview TestSwitchPattern
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:233)
at TestSwitchPattern.main(TestSwitchPattern.java:5)
Devoxx France 2023
Sciam
Java 20 : quatrième preview apporte deux évolutions
Pattern Matching for switch (Preview)
Lorsque l’exhaustivité des cas d’un switch n’est pas satisfaite
Exemple : sur un type scellé ou une énumération par exemple
Une exception est levée au runtime
Java 19 : java.lang.IncompatibleClassChangeError
Java 20 : java.lang.MatchException
Le support de l'inférence pour les arguments de type
Pour les records pattern avec génériques
Devoxx France 2023
Sciam
Les fonctionnalités du projet Panama
Foreign Function & Memory API
Vector API
Devoxx France 2023
Sciam
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
Foreign Function & Memory API (Preview)
Proposée en incubation en Java 17 (JEP 412) et Java 18 (JEP 419)
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 preview en Java 19 (JEP 424) et 20 (JEP 434)
Elle est maintenant est dans le module java.base
Attention : cette API évolue beaucoup
Dans chacune des versions de Java où elle est proposée
Devoxx France 2023
Sciam
L’API de bas niveau
Foreign Function & Memory API (Preview)
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)
2) Pour invoquer du code natif
Une future alternative à l’API JNI présente depuis Java 1.1
Devoxx France 2023
Sciam
Exemple Java 20 sous Windows
Foreign Function & Memory API (Preview)
public class HelloFFM {
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.openConfined()) {
MemorySegment cStringMessage = offHeap.allocateUtf8String("Voulez-vous utiliser Java 20 ?");
MemorySegment cStringTitre = offHeap.allocateUtf8String("Confirmation");
int bouton = (int) methodHandle.invoke(NULL, cStringMessage, cStringTitre, 36);
System.out.println("Bouton selectionne : " + bouton);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Devoxx France 2023
Sciam
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 architectures CPU supportées : x64 (SSE et AVX) et AArch64 (Neon)
Vector API (Incubator)
En incubation en Java 16 (JEP 338), 17 (JEP 414), 18 (JEP 417),
19 (JEP 426) et 20 (JEP 438)
Dans le module jdk.incubator.vector
Single Instruction, Multiple Data
Traiter en parallèle de tableaux de données, sans threads
Pour appliquer une même opération sur les valeurs traitées
En un seul cycle de traitement CPU
Devoxx France 2023
Sciam
API plutôt de bas niveau, verbeuse, dépendant partiellement du CPU
Mais qui peut offrir de meilleures performances que le code scalaire équivalent
Vector API (Incubator)
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;
}
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;
}
Exemple Java 20
Devoxx France 2023
Sciam
Les fonctionnalités du projet Loom
Virtual Threads
Structured Concurrency
Scoped values
Devoxx France 2023
Sciam
Chaque thread Java est directement mappé à un thread de l’OS
Depuis Java 1.0
Virtual Threads (Preview)
Décharge la JVM de se préoccuper de tâches réalisées par l’OS
Ordonnancement et changement de contexte des threads
Ce modèle n’est pas optimal
Car un thread de la plateforme est coûteux en ressources
Notamment à cause de la taille fixe (par défaut) de sa pile
Cela limite le nombre de threads qui peuvent être utilisés
Or on utilise de plus en plus de threads
Qui généralement passent beaucoup de temps à attendre
La fin d’une opération bloquante
Devoxx France 2023
Sciam
Introduction d’un nouveau type de threads : des threads virtuels
Virtual Threads (Preview)
Ce sont des threads « légers » gérés par la JVM
Non lié à un thread de la plate-forme dédié
Qu’il utilise uniquement lors de l’utilisation de la CPU par ses traitements
En preview Java 19 (JEP 425) et 20 (JEP 436)
Plusieurs objectifs :
• Conserver le style « un thread par requête »
Avec une meilleure utilisation des ressources requises
• Assurer une adoption par le code existant
Qui utilise l'API java.lang.Thread avec un impact minimum
• Permettre le débogage, le profilage et le dépannage
Avec les outils existants du JDK
Devoxx France 2023
Sciam
Exécutent du code qui ne bloque pas les threads de l’OS
En attendant des verrous, ou la fin d’opérations bloquantes (I/O par exemple)
Virtual Threads (Preview)
Mapping M:N entre threads virtuels et threads de l’OS
Grâce à un ForkJoinPool dédié qui fournit les threads porteurs (carrier threads)
Si le thread virtuel exécute une action bloquante dans les API du JDK
La JVM enregistrement la stack dans le heap et exécute l’action en non bloquante
Le thread porteur peut alors exécuter un autre thread virtuel
Une fois l’action non bloquante terminée
L’exécution des traitements du thread virtuel est reprise sur un thread porteur
Potentiellement différent
Ce mécanisme est géré en interne par les API du JDK
En utilisant des Continuation et ContinuationScope
Et est transparent pour le développeur
Devoxx France 2023
Sciam
Pas de constructeur public
Virtual Threads (Preview)
Le plus simple est d’utiliser Thread.startVirtualThread()
Pour démarrer un nouveau thread virtuel qui exécute un Runnable
Thread t = Thread.startVirtualThread(() -> {
System.out.println("Thread : " + Thread.currentThread());
});
L’interface scellée Thread.Buidler propose deux interfaces filles
Thread.Builder.OfVirtual et Thread.Builder.OfPlatform
Dont on obtient une instance avec Thread::ofVirtual et Thread::ofPlatform
var threadVirtuel = Thread.ofVirtual().name("app-thread-virtuel-", 0).start(() -> {
System.out.println(Thread.currentThread());
});
threadVirtuel.join();
Devoxx France 2023
Sciam
Ne pas mettre les threads virtuels dans un pool
Aucune utilité vue leur faible coût de création
Virtual Threads (Preview)
Plusieurs restrictions sur les threads virtuels :
• Ils sont obligatoirement des threads démons
• La priorité est obligatoirement Thread.NORM_PRIORITY
• stop(), resume(), suspend() lèvent une UnsupportedOperationException
• Ils ne peuvent pas être associés à un ThreadGroup
• getThreadGroup() renvoie un groupe "VirtualThreads" fictif qui est vide
• getAllStackTraces() renvoie une Map qui contient uniquement que les threads de l’OS
plutôt que de tous les threads
Devoxx France 2023
Sciam
Peuvent améliorer le débit des applications
Lorsque le nombre de tâches simultanées est important
Et que les tâches ne requièrent pas de manière intensive la CPU
Virtual Threads (Preview)
• L’exécution d’un bloc de code synchronized
Il est préférable d’utiliser si possible un ReentrantLock
Des scénarios bloquants peuvent limiter l’intérêt des threads virtuels
Car ils laissent le thread virtuel associé à son thread porteur
• Lors de l’exécution d’une méthode native
Un événement JFR : jdk.VirtualThreadPinned
Option de la JVM pour identifier ces cas
-Djdk.tracePinnedThreads=full ou short
Devoxx France 2023
Sciam
Propose un nouveau modèle de programmation
Structured Concurrency (Incubator)
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é
Grâce au traitement de plusieurs tâches
Exécutées dans différents threads virtuels comme une seule unité de travail
Fork/Join et concurrence structurée sont complémentaires
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
Devoxx France 2023
Sciam
API en incubation
Ajout de son module au graphe à la compilation et à l’exécution
Structured Concurrency (Incubator)
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
Classe principale : jdk.incubator.concurrent.StructuredTaskScope
--add-modules jdk.incubator.concurrent
Devoxx France 2023
Sciam
La mise en œuvre en plusieurs étapes
Structured Concurrency (Incubator)
• 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()) {
Future<Client> clientFuture = scope.fork(() -> this.getClient(codeClient));
Future<Commande> commandeFuture = scope.fork(() -> this.getCommande(idCommande));
scope.joinUntil(Instant.now().plusSeconds(15));
resultat = this.genererFacture(clientFuture.get(), commandeFuture.get());
}
return resultat;
}
• Invoquer la méthode fork() pour chaque sous-tâches à exécuter
• Attendre la fin de l’exécution des sous-tâches
o Soit avec timout en utilisant la méthode joinUntil()
o Soit sans timeout en utilisant la méthode join()
• Exploiter les résultats obtenus dans des instances de type Future
Devoxx France 2023
Sciam
La classe StructuredTaskScope.ShutdownOnFailure
Propose un modèle invoke all
Structured Concurrency (Incubator)
Facture getFacture(String codeClient, long idCommande)
throws ExecutionException, InterruptedException, TimeoutException {
Facture resultat = null;
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<Client> clientFuture = scope.fork(() -> this.getClient(codeClient));
Future<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
Devoxx France 2023
Sciam
La classe StructuredTaskScope.ShutdownOnSuccess
Propose un modèle invoke any
Structured Concurrency (Incubator)
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
Devoxx France 2023
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
Structured Concurrency (Incubator)
class ComposantLePlusLegerScope extends StructuredTaskScope<Composant> {
private final Collection<Composant> composants = new ConcurrentLinkedQueue<>();
private final Collection<Throwable> exceptions = new ConcurrentLinkedQueue<>();
@Override
protected void handleComplete(Future<Composant> future) {
switch (future.state()) {
case RUNNING -> {}
case SUCCESS -> this.composants.add(future.resultNow());
case FAILED -> this.exceptions.add(future.exceptionNow());
case CANCELLED -> {}
}
}
Devoxx France 2023
Sciam
Structured Concurrency (Incubator)
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);
}
}
Devoxx France 2023
Sciam
Pour partager des objets dans le code exécuté par un thread
Historiquement depuis Java 1.2, on utilise une variable de type ThreadLocal
Scoped values (Incubator)
L’API ScopedValue tente de remédier à ces inconvénients
Mais cela présente plusieurs risques :
Mutable, fuite de mémoire, consommation de ressources,
Stocker et de partager des données immuables
Pour une durée de vie limitée à des traitements du thread qui les a écrits
public final static ScopedValue<String> VALEUR = ScopedValue.newInstance();
Création d’une instance généralement statique
Devoxx France 2023
Sciam
where() pour définir une valeur, chainable pour plusieurs valeurs
Scoped values (Incubator)
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(TestScopedValue::traiter);
get() pour obtenir la valeur ou lève une NoSuchElementException
isBound() pour savoir si une valeur est associée au thread
System.out.println((VALEUR.isBound() ? VALEUR.get() : "non definie"));
Exécuter une tâche dans le thread courant
Devoxx France 2023
Sciam
Réassociation d’une valeur pour un traitement sous-jacent
Scoped values (Incubator)
Partage avec les threads virtuels d’une StucturedTaskScope
ScopedValue.where(VALEUR, "valeur").run(() -> {
afficherValeur();
ScopedValue.where(VALEUR, "autre-valeur")
.run(MaClasse::traiter);
afficherValeur();
});
ScopedValue.where(VALEUR, "valeur", () -> {
try (var scope = new StructuredTaskScope<String>()) {
afficherValeur();
scope.fork(MaClasse::traiter);
scope.fork(MaClasse::traiter);
scope.joinUntil(Instant.now().plusSeconds(10));
} catch (InterruptedException | TimeoutException e) {
e.printStackTrace();
}
});
Devoxx France 2023
Sciam
Les autres évolutions
Dans les API
Dans les outils
Concernant la sécurité
Concernant la performance
Devoxx France 2023
Sciam
Java 19, JSR 422
Linux/RISC-V Port
Peu d’appareil grand public utilisant RISC-V actuellement
Mais cela risque de changer dans un futur proche
De nombreux acteurs envisagent son utilisant notamment :
Apple, la NASA, de nombreux industriels asiatiques notamment chinois et indiens
Anticipe cela avec le portage d’OpenJDK sur Linux/RISC-V
Qui est intégré au repository principal
RISC-V est une architecture de jeu d'instructions (ISA) RISC libre et gratuite
Conçu à l'origine à l'Université Berkeley de Californie
Maintenant développé collaborativement sous le parrainage de RISC-V International
Devoxx France 2023
Sciam
Les autres évolutions
Dans les API
Devoxx France 2023
Sciam
Modification du comportement de méthodes
La classe ThreadGroup
• destroy() : les invocations sont ignorées
• isDaemon() : renvoie la valeur du flag qui n’a plus d’utilité
• isDestroyed() : renvoie toujours false
• setDaemon() : positionne le flag mais n’a plus aucun effet
• suspend(), resume(), stop() : lève une UnsupportedOperationException
Devoxx France 2023
Sciam
La spécification de ces méthodes est désormais plus stricte
Que dans les versions précédentes et la nouvelle implémentation la respecte
Double.toString(double) et Float.toString(float)
Peuvent retourner des résultats légèrement différents
C:java>jshell
| Welcome to JShell -- Version 18
| For an introduction type: /help intro
jshell> Double.toString(2e23)
$1 ==> "1.9999999999999998E23"
jshell> Double.toString(1e-323)
$2 ==> "1.0E-323"
jshell> Double.toString(8.41E21)
$4 ==> "8.409999999999999E21"
C:java>jshell
| Welcome to JShell -- Version 19
| For an introduction type: /help intro
jshell> Double.toString(2e23)
$1 ==> "2.0E23"
jshell> Double.toString(1e-323)
$2 ==> "9.9E-324"
jshell> Double.toString(8.41E21)
$4 ==> "8.41E21"
Devoxx France 2023
Sciam
Historiquement, 4 styles prédéfinis :
FormatStyle.FULL, LONG, MEDIUM et SHORT
Formatage de date/heure supplémentaire
Possible de spécifier son propre style
Qui va tenir compte de la Locale par défaut
DateTimeFormatter::ofLocalizedPattern(String)
DateTimeFormatterBuilder::appendLocalized(String)
septembre 2022
September 2022
DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedPattern("yMMMMM");
LocalDate date = LocalDate.of(2022, 9, 20);
System.out.println(date.format(dtf));
Locale.setDefault(Locale.US);
dtf = DateTimeFormatter.ofLocalizedPattern("yMMMMM");
System.out.println(date.format(dtf));
Devoxx France 2023
Sciam
Nouvelles méthodes pour créer des HashMaps et des HashSets
Et dérivée dont la taille est préallouée
Pouvant accueillir le nombre d’éléments passé en paramètre
Sans déclencher un nombre potentiellement important de resize
Fabriques pour instancier des HashMaps et HashSets
avec une taille préallouée
• HashMap.newHashMap(int)
• HashSet.newHashSet(int)
• LinkedHashMap.newLinkedHashMap(int)
• LinkedHashSet.newLinkedHashSet(int)
• WeakHashMap.newWeakHashMap(int)
A utiliser de préférence à la surcharge des constructeurs
Qui attend un paramètre de type int
Surtout pour des collections de grandes tailles
Devoxx France 2023
Sciam
Les autres évolutions
Dans les outils
Devoxx France 2023
Sciam
Dans le JDK 19, javac supporte les versions 7 à 19 incluses
Le support de Java 7 par javac
C:java>javac -version
javac 19
C:java>javac --release=7 Hello.java
warning: [options] source value 7 is obsolete and will be removed in a future release
warning: [options] target value 7 is obsolete and will be removed in a future release
warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
3 warnings
Dans le JDK 20, javac ne supporte plus la version 7
C:java>javac -version
javac 20
C:java>javac --release=7 Hello.java
error: release version 7 not supported
Usage: javac <options> <source files>
use --help for a list of possible options
Devoxx France 2023
Sciam
Nouvel avertissement du compilateur
et sont souvent considérées comme équivalentes
a += b; a = a + b;
short a = 1;
int b = 2;
a += b;
short a = 1;
int b = 2;
a = a + b;
Java 20 : avertissement du compilateur
C:java>javac -Xlint Addition2.java
Addition2.java:6: warning: [lossy-conversions] implicit cast from int to short in compound
assignment is possibly lossy
a += b;
^
1 warning
C:java>javac Addition1.java
Addition1.java:6: error: incompatible types: possible lossy
conversion from int to short
a = a + b;
^
1 error
6: iadd
7: i2s
8: istore_1
C:java>javac Addition2.java
C:java>
Devoxx France 2023
Sciam
JShell affiche les éléments dépréciés de manière singulière
Affichage dans JShell
Et met en évidence les variables et les mots-clés dans la console
Devoxx France 2023
Sciam
Syntaxe de recherche a été améliorée
Pour permettre la recherche de plusieurs termes
Recherche dans la Javadoc
Devoxx France 2023
Sciam
Les autres évolutions
Concernant la sécurité
Devoxx France 2023
Sciam
Un renforcement de la sécurité par défaut de la plate-forme Java
La sécurité
Des performances de TLS améliorées
L'ajout au KeyStore
Du support pour accéder aux certificats de la machine locale sous Windows
Le support des CBT
Pour l'authentification Negotiate/Kerberos sur HTTPS
Java 19
Java 20
DTLS 1.0 est désactivé par défaut
Algorithmes EDCH de TLS sont désactivés par défaut
Devoxx France 2023
Sciam
Les autres évolutions
Concernant la performance
Devoxx France 2023
Sciam
Java 19
Les améliorations de performance
Java 20
Génération automatique de l’archive AppCDS avec une seule option
+XX:AutoCreateSharedArchive et +XX:SharedArchiveFile=mon-app.jsa
Améliorations dans le ramasse-miettes G1
Nouveaux intrinsics pour x86_64 et aarch64 pour différents algorithmes :
Chacha20, Poly1305, MD5, …
Devoxx France 2023
Sciam
Conclusion
Devoxx France 2023
Sciam
Java poursuit son évolution en respectant son modèle de releases
Conclusion
Cela permettra à Java de rester pertinent aujourd’hui et demain
Concernant la syntaxe, particulièrement le pattern matching
Java 19 et 20 proposent des fonctionnalités en preview ou incubation
Concernant une meilleure utilisation du matériel moderne
Concernant la programmation parallèle et concurrente
Et de nombreuses améliorations relatives
À la performances
À la sécurité
Aux API
À l’outillage
Devoxx France 2023
Sciam
N’hésitez pas à télécharger et tester une distribution du JDK 20
Auprès d’un fournisseur :
Conclusion
Java 21 en septembre 2023
Pour anticiper la release de la prochaine version LTS de Java
Temurin (Eclipse Adoptium) : https://adoptium.net/temurin/releases/?version=20
Liberica (BellSoft) : https://bell-sw.com/libericajdk/
Oracle OpenJDK (Oracle) : https://jdk.java.net/20/
SapMachine (SAP) : https://sap.github.io/SapMachine/
Zulu (Azul) : https://www.azul.com/downloads/zulu-community/
Corretto (Amazon) : https://aws.amazon.com/fr/corretto/ (Java 19 actuellement)
Dans laquelle plusieurs fonctionnalités
En preview ou incubation depuis plusieurs semestres
Pourraient devenir standards
Devoxx France 2023
Sciam
Merci pour votre attention
Devoxx France 2023
Sciam
Questions ?

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

Arquitetura Node com NestJS
Arquitetura Node com NestJSArquitetura Node com NestJS
Arquitetura Node com NestJS
 
Support cours angular
Support cours angularSupport cours angular
Support cours angular
 
Introduction à Angular
Introduction à AngularIntroduction à Angular
Introduction à Angular
 
Angular Avancé
Angular AvancéAngular Avancé
Angular Avancé
 
Workshop Spring - Session 1 - L'offre Spring et les bases
Workshop Spring  - Session 1 - L'offre Spring et les basesWorkshop Spring  - Session 1 - L'offre Spring et les bases
Workshop Spring - Session 1 - L'offre Spring et les bases
 
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka StreamsTraitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
 
Présentation Angular 2
Présentation Angular 2 Présentation Angular 2
Présentation Angular 2
 
Building Web Apps with WebAssembly and Blazor
Building Web Apps with WebAssembly and BlazorBuilding Web Apps with WebAssembly and Blazor
Building Web Apps with WebAssembly and Blazor
 
Support de cours technologie et application m.youssfi
Support de cours technologie et application m.youssfiSupport de cours technologie et application m.youssfi
Support de cours technologie et application m.youssfi
 
Modélisation de données pour MongoDB
Modélisation de données pour MongoDBModélisation de données pour MongoDB
Modélisation de données pour MongoDB
 
Examen principal - PHP
Examen principal - PHPExamen principal - PHP
Examen principal - PHP
 
Jenkins
JenkinsJenkins
Jenkins
 
La gestion des exceptions avec Java
La gestion des exceptions avec JavaLa gestion des exceptions avec Java
La gestion des exceptions avec Java
 
Support NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDBSupport NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDB
 
softCours design pattern m youssfi partie 9 creation des objets abstract fact...
softCours design pattern m youssfi partie 9 creation des objets abstract fact...softCours design pattern m youssfi partie 9 creation des objets abstract fact...
softCours design pattern m youssfi partie 9 creation des objets abstract fact...
 
Presentation SOAP
 Presentation SOAP Presentation SOAP
Presentation SOAP
 
Polymorphisme, interface et classe abstraite
Polymorphisme, interface et classe abstraitePolymorphisme, interface et classe abstraite
Polymorphisme, interface et classe abstraite
 
Cours design pattern m youssfi partie 7 facade bridge flyweight
Cours design pattern m youssfi partie 7 facade bridge flyweightCours design pattern m youssfi partie 7 facade bridge flyweight
Cours design pattern m youssfi partie 7 facade bridge flyweight
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring boot
 
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiJava entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
 

Similar a Devoxx France 2023 - Les nouveautés de Java 19 et 20

Similar a Devoxx France 2023 - Les nouveautés de Java 19 et 20 (20)

Les nouveautés de Java 19, 20 et 21 - RivieraDev 2023
Les nouveautés de Java 19, 20 et 21 - RivieraDev 2023Les nouveautés de Java 19, 20 et 21 - RivieraDev 2023
Les nouveautés de Java 19, 20 et 21 - RivieraDev 2023
 
En route vers Java 21 - Javaday Paris 2023
En route vers Java 21 - Javaday Paris 2023En route vers Java 21 - Javaday Paris 2023
En route vers Java 21 - Javaday Paris 2023
 
Les nouveautés de Java 21 - Rencontres dev Toulon octobre 2023.pdf
Les nouveautés de Java 21 - Rencontres dev Toulon octobre 2023.pdfLes nouveautés de Java 21 - Rencontres dev Toulon octobre 2023.pdf
Les nouveautés de Java 21 - Rencontres dev Toulon octobre 2023.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
 
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
 
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
 
Back to the future of java (from 8 to 11 and beyond)
Back to the future of java (from 8 to 11 and beyond)Back to the future of java (from 8 to 11 and beyond)
Back to the future of java (from 8 to 11 and beyond)
 
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
 
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
 
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
 
Javascript Json artchitecture
Javascript  Json artchitecture Javascript  Json artchitecture
Javascript Json artchitecture
 
JAVA Chapitre1
JAVA Chapitre1 JAVA Chapitre1
JAVA Chapitre1
 
Les Threads.ppt
Les Threads.pptLes Threads.ppt
Les Threads.ppt
 
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
 
Marzouk une introduction à jdbc
Marzouk une introduction à jdbcMarzouk une introduction à jdbc
Marzouk une introduction à jdbc
 
Reseau
ReseauReseau
Reseau
 
programmation réseau en java
programmation réseau en java programmation réseau en java
programmation réseau en java
 
Chap1_PresentationJava.pdf
Chap1_PresentationJava.pdfChap1_PresentationJava.pdf
Chap1_PresentationJava.pdf
 
Annotation Java vs. Decorator Python
Annotation Java vs. Decorator PythonAnnotation Java vs. Decorator Python
Annotation Java vs. Decorator Python
 

Más de Jean-Michel Doudoux

Más de Jean-Michel Doudoux (10)

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
 
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
 
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
 
"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
 

Devoxx France 2023 - Les nouveautés de Java 19 et 20

  • 1. Devoxx France 2023 Les nouveautés de Java 19 et 20 JMdoudouX Sciam
  • 2. Devoxx France 2023 Sciam Java poursuit son évolution En respectant le rythme de release tous les 6 mois Java 19 et 20 Java 19 Java 20 Publication 20 septembre 2022 21 mars 2023 Spécification JSR 394 JSR 395 Implémentation de référence OpenJDK 19 OpenJDK 20 Durée des patchs 6 mois 6 mois Nb JEPs 7 7
  • 3. Devoxx France 2023 Sciam Quelques fonctionnalités Quasiment toutes en preview ou incubation Les JEPs de Java version 19 et 20 Java 19 Java 20 Record Patterns 405 (Preview) 432 (Second Preview) Foreign Function & Memory API 424 (Preview) 434 (Second Preview) Virtual Threads 425 (Preview) 436 (Second Preview) Pattern Matching for switch 427 (Third Preview) 433 (Fourth Preview) Vector API 426 (Fourth Incubator) 438 (Fifth Incubator) Structured Concurrency 428 (Incubator) 437 (Second Incubator) Scoped Values 419 (Incubator) Linux/RISC-V Port 422
  • 4. Devoxx France 2023 Sciam Jean-Michel Doudoux Senior Tech Lead chez Auteur de 2 didacticiels Diffusés sous licence GNU FDL • Développons en Java (4000 pages) • Développons en Java avec Eclipse Co-fondateur du https://www.jmdoudoux.fr @jmdoudoux
  • 5. Devoxx France 2023 Sciam Roadmap Les fonctionnalités des JEPs du projet Amber du projet Panama du projet Loom Les autres évolutions
  • 6. Devoxx France 2023 Sciam Les fonctionnalités du projet Amber Record Patterns Pattern Matching for switch
  • 7. Devoxx France 2023 Sciam Type pattern utilisable avec le pattern matching sur les records Record Patterns (Preview) Ajouter un nouveau pattern utilisable dans le pattern matching Le record pattern pour déconstruire les valeurs d’un record record Employe(String nom, String prenom) {} Object o = new Employe("Nom1", "Prenom1"); if (o instanceof Employe emp) { System.out.println("Employe : "+emp.nom()+" "+emp.prenom()); } if (o instanceof Employe(String nom, String prenom)) { System.out.println("Employe : "+nom+" "+prenom); } En preview en Java 19 (JEP 420) et 20 (JEP 432)
  • 8. Devoxx France 2023 Sciam Java 19 : utilisable avec une instruction instanceof ou switch Record Patterns (Preview) Java 20 : utilisable dans une boucle for améliorée Type pattern et record pattern peuvent être combinés Dans un même switch switch (o) { case Employe emp -> System.out.println(emp); case Grade(String code, String designation) -> System.out.println("Grade " + designation + "(" + code + ")"); default -> System.out.println("Type non supporté"); } List<Employe> employes = List.of(new Employe("Nom1", "Prenom1")); for(Employe(var nom, var prenom) : employes) { System.out.println(nom + " " + prenom); } Un élément null lève une java.lang.MatchException
  • 9. Devoxx France 2023 Sciam Le nom des composants peut être différents Seuls l’ordre et le type des composants doivent être respectés Record Patterns (Preview) Utilisation possible de l’inférence du type dans le pattern if (o instanceof Employe(String n, String p)) { System.out.println("Employe : " + n + " " + p); } if (o instanceof Employe(var nom, var prenom)) { System.out.println("Employe : "+nom+" "+prenom); }
  • 10. Devoxx France 2023 Sciam Java 19 Record Patterns (Preview) if (o instanceof Employe(var nom, var prenom) emp) { System.out.println("Employe : " + nom + " " + prenom + " {" + emp + "}" ); } Possibilité de définir une variable qui permet d’accéder à l’instance Record pattern nommé (named record pattern) Java 20 : fonctionnalité retirée
  • 11. Devoxx France 2023 Sciam Les record patterns peuvent être imbriqués Record Patterns (Preview) La valeur null ne correspond à aucun 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, Grade(var code, var designation))) { System.out.println("Employe : " + nom + " " + prenom + ", "+ designation); }
  • 12. Devoxx France 2023 Sciam Avec un record générique Record Patterns (Preview) Java 20 : support de l'inférence des types d’arguments génériques Java 19 : pas de déconstruction d’un type brut if (monoDeMono instanceof Mono<Mono<String>>(Mono<String>(var s))) { System.out.println("mono contient " + s); } if (monoDeMono instanceof Mono(Mono(var s))) { System.out.println("mono contient " + s); } record Mono<T>(T val) implements Container<T> {} Mono<Mono<String>> monoDeMono = new Mono<>(new Mono<>("valeur"));
  • 13. Devoxx France 2023 Sciam Historiquement en preview en Java 17 (JEP 406), 18 (JEP 420), 19 (JEP 427) et 20 (JEP 433) Pattern Matching for switch (Preview) Utiliser le pattern matching dans une instruction switch Avec support de la valeur null contrairement à la levée historique d’une NPE Exemple en Java 18 static String getDesignation(Object obj) { String designation = switch (obj) { case Terrain t && (t.getSurface() > 1000) -> "Grand terrain"; case Terrain t -> "Petit terrain"; case null -> "Instance null"; default -> "Pas un terrain"; }; return designation; }
  • 14. Devoxx France 2023 Sciam Java 19 : troisième preview apporte deux évolutions Pattern Matching for switch (Preview) Le guarded pattern utilise le nouveau mot clé contextuel when À la place de l’opérateur && dans les précédentes preview static String getDesignation(Object obj) { String designation = switch (obj) { case Terrain t when (t.getSurface() > 1000) -> "Grand terrain"; case Terrain t -> "Petit terrain"; case null -> "Instance null"; default -> "Pas un terrain"; }; return designation; }
  • 15. Devoxx France 2023 Sciam Sémantique d'exécution d’un switch avec le pattern matching Lorsque la valeur est null et que le cas null n’est pas explicitement géré : Elle est plus étroitement alignée sur la sémantique historique des switchs Pattern Matching for switch (Preview) public static void main(String[] args) { String chaine = null; switch (chaine) { case String s -> { System.out.println("traitement chaine"); System.out.println("taille : " + s.length()); } } }
  • 16. Devoxx France 2023 Sciam Java 18 Pattern Matching for switch (Preview) C:java>javac --enable-preview --release 18 -g TestSwitchPattern.java Note: TestSwitchPattern.java uses preview features of Java SE 18. C:java>java --enable-preview TestSwitchPattern traitement chaine Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "s" is null at TestSwitchPattern.main(TestSwitchPattern.java:8) Java 19 C:java>javac --enable-preview --release 19 TestSwitchPattern.java Note: TestSwitchPattern.java uses preview features of Java SE 19. C:java>java --enable-preview TestSwitchPattern Exception in thread "main" java.lang.NullPointerException at java.base/java.util.Objects.requireNonNull(Objects.java:233) at TestSwitchPattern.main(TestSwitchPattern.java:5)
  • 17. Devoxx France 2023 Sciam Java 20 : quatrième preview apporte deux évolutions Pattern Matching for switch (Preview) Lorsque l’exhaustivité des cas d’un switch n’est pas satisfaite Exemple : sur un type scellé ou une énumération par exemple Une exception est levée au runtime Java 19 : java.lang.IncompatibleClassChangeError Java 20 : java.lang.MatchException Le support de l'inférence pour les arguments de type Pour les records pattern avec génériques
  • 18. Devoxx France 2023 Sciam Les fonctionnalités du projet Panama Foreign Function & Memory API Vector API
  • 19. Devoxx France 2023 Sciam 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 Foreign Function & Memory API (Preview) Proposée en incubation en Java 17 (JEP 412) et Java 18 (JEP 419) 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 preview en Java 19 (JEP 424) et 20 (JEP 434) Elle est maintenant est dans le module java.base Attention : cette API évolue beaucoup Dans chacune des versions de Java où elle est proposée
  • 20. Devoxx France 2023 Sciam L’API de bas niveau Foreign Function & Memory API (Preview) 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) 2) Pour invoquer du code natif Une future alternative à l’API JNI présente depuis Java 1.1
  • 21. Devoxx France 2023 Sciam Exemple Java 20 sous Windows Foreign Function & Memory API (Preview) public class HelloFFM { 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.openConfined()) { MemorySegment cStringMessage = offHeap.allocateUtf8String("Voulez-vous utiliser Java 20 ?"); MemorySegment cStringTitre = offHeap.allocateUtf8String("Confirmation"); int bouton = (int) methodHandle.invoke(NULL, cStringMessage, cStringTitre, 36); System.out.println("Bouton selectionne : " + bouton); } } catch (Throwable t) { t.printStackTrace(); } } }
  • 22. Devoxx France 2023 Sciam 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 architectures CPU supportées : x64 (SSE et AVX) et AArch64 (Neon) Vector API (Incubator) En incubation en Java 16 (JEP 338), 17 (JEP 414), 18 (JEP 417), 19 (JEP 426) et 20 (JEP 438) Dans le module jdk.incubator.vector Single Instruction, Multiple Data Traiter en parallèle de tableaux de données, sans threads Pour appliquer une même opération sur les valeurs traitées En un seul cycle de traitement CPU
  • 23. Devoxx France 2023 Sciam API plutôt de bas niveau, verbeuse, dépendant partiellement du CPU Mais qui peut offrir de meilleures performances que le code scalaire équivalent Vector API (Incubator) 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; } 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; } Exemple Java 20
  • 24. Devoxx France 2023 Sciam Les fonctionnalités du projet Loom Virtual Threads Structured Concurrency Scoped values
  • 25. Devoxx France 2023 Sciam Chaque thread Java est directement mappé à un thread de l’OS Depuis Java 1.0 Virtual Threads (Preview) Décharge la JVM de se préoccuper de tâches réalisées par l’OS Ordonnancement et changement de contexte des threads Ce modèle n’est pas optimal Car un thread de la plateforme est coûteux en ressources Notamment à cause de la taille fixe (par défaut) de sa pile Cela limite le nombre de threads qui peuvent être utilisés Or on utilise de plus en plus de threads Qui généralement passent beaucoup de temps à attendre La fin d’une opération bloquante
  • 26. Devoxx France 2023 Sciam Introduction d’un nouveau type de threads : des threads virtuels Virtual Threads (Preview) Ce sont des threads « légers » gérés par la JVM Non lié à un thread de la plate-forme dédié Qu’il utilise uniquement lors de l’utilisation de la CPU par ses traitements En preview Java 19 (JEP 425) et 20 (JEP 436) Plusieurs objectifs : • Conserver le style « un thread par requête » Avec une meilleure utilisation des ressources requises • Assurer une adoption par le code existant Qui utilise l'API java.lang.Thread avec un impact minimum • Permettre le débogage, le profilage et le dépannage Avec les outils existants du JDK
  • 27. Devoxx France 2023 Sciam Exécutent du code qui ne bloque pas les threads de l’OS En attendant des verrous, ou la fin d’opérations bloquantes (I/O par exemple) Virtual Threads (Preview) Mapping M:N entre threads virtuels et threads de l’OS Grâce à un ForkJoinPool dédié qui fournit les threads porteurs (carrier threads) Si le thread virtuel exécute une action bloquante dans les API du JDK La JVM enregistrement la stack dans le heap et exécute l’action en non bloquante Le thread porteur peut alors exécuter un autre thread virtuel Une fois l’action non bloquante terminée L’exécution des traitements du thread virtuel est reprise sur un thread porteur Potentiellement différent Ce mécanisme est géré en interne par les API du JDK En utilisant des Continuation et ContinuationScope Et est transparent pour le développeur
  • 28. Devoxx France 2023 Sciam Pas de constructeur public Virtual Threads (Preview) Le plus simple est d’utiliser Thread.startVirtualThread() Pour démarrer un nouveau thread virtuel qui exécute un Runnable Thread t = Thread.startVirtualThread(() -> { System.out.println("Thread : " + Thread.currentThread()); }); L’interface scellée Thread.Buidler propose deux interfaces filles Thread.Builder.OfVirtual et Thread.Builder.OfPlatform Dont on obtient une instance avec Thread::ofVirtual et Thread::ofPlatform var threadVirtuel = Thread.ofVirtual().name("app-thread-virtuel-", 0).start(() -> { System.out.println(Thread.currentThread()); }); threadVirtuel.join();
  • 29. Devoxx France 2023 Sciam Ne pas mettre les threads virtuels dans un pool Aucune utilité vue leur faible coût de création Virtual Threads (Preview) Plusieurs restrictions sur les threads virtuels : • Ils sont obligatoirement des threads démons • La priorité est obligatoirement Thread.NORM_PRIORITY • stop(), resume(), suspend() lèvent une UnsupportedOperationException • Ils ne peuvent pas être associés à un ThreadGroup • getThreadGroup() renvoie un groupe "VirtualThreads" fictif qui est vide • getAllStackTraces() renvoie une Map qui contient uniquement que les threads de l’OS plutôt que de tous les threads
  • 30. Devoxx France 2023 Sciam Peuvent améliorer le débit des applications Lorsque le nombre de tâches simultanées est important Et que les tâches ne requièrent pas de manière intensive la CPU Virtual Threads (Preview) • L’exécution d’un bloc de code synchronized Il est préférable d’utiliser si possible un ReentrantLock Des scénarios bloquants peuvent limiter l’intérêt des threads virtuels Car ils laissent le thread virtuel associé à son thread porteur • Lors de l’exécution d’une méthode native Un événement JFR : jdk.VirtualThreadPinned Option de la JVM pour identifier ces cas -Djdk.tracePinnedThreads=full ou short
  • 31. Devoxx France 2023 Sciam Propose un nouveau modèle de programmation Structured Concurrency (Incubator) 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é Grâce au traitement de plusieurs tâches Exécutées dans différents threads virtuels comme une seule unité de travail Fork/Join et concurrence structurée sont complémentaires 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
  • 32. Devoxx France 2023 Sciam API en incubation Ajout de son module au graphe à la compilation et à l’exécution Structured Concurrency (Incubator) 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 Classe principale : jdk.incubator.concurrent.StructuredTaskScope --add-modules jdk.incubator.concurrent
  • 33. Devoxx France 2023 Sciam La mise en œuvre en plusieurs étapes Structured Concurrency (Incubator) • 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()) { Future<Client> clientFuture = scope.fork(() -> this.getClient(codeClient)); Future<Commande> commandeFuture = scope.fork(() -> this.getCommande(idCommande)); scope.joinUntil(Instant.now().plusSeconds(15)); resultat = this.genererFacture(clientFuture.get(), commandeFuture.get()); } return resultat; } • Invoquer la méthode fork() pour chaque sous-tâches à exécuter • Attendre la fin de l’exécution des sous-tâches o Soit avec timout en utilisant la méthode joinUntil() o Soit sans timeout en utilisant la méthode join() • Exploiter les résultats obtenus dans des instances de type Future
  • 34. Devoxx France 2023 Sciam La classe StructuredTaskScope.ShutdownOnFailure Propose un modèle invoke all Structured Concurrency (Incubator) Facture getFacture(String codeClient, long idCommande) throws ExecutionException, InterruptedException, TimeoutException { Facture resultat = null; try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { Future<Client> clientFuture = scope.fork(() -> this.getClient(codeClient)); Future<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
  • 35. Devoxx France 2023 Sciam La classe StructuredTaskScope.ShutdownOnSuccess Propose un modèle invoke any Structured Concurrency (Incubator) 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
  • 36. Devoxx France 2023 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 Structured Concurrency (Incubator) class ComposantLePlusLegerScope extends StructuredTaskScope<Composant> { private final Collection<Composant> composants = new ConcurrentLinkedQueue<>(); private final Collection<Throwable> exceptions = new ConcurrentLinkedQueue<>(); @Override protected void handleComplete(Future<Composant> future) { switch (future.state()) { case RUNNING -> {} case SUCCESS -> this.composants.add(future.resultNow()); case FAILED -> this.exceptions.add(future.exceptionNow()); case CANCELLED -> {} } }
  • 37. Devoxx France 2023 Sciam Structured Concurrency (Incubator) 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); } }
  • 38. Devoxx France 2023 Sciam Pour partager des objets dans le code exécuté par un thread Historiquement depuis Java 1.2, on utilise une variable de type ThreadLocal Scoped values (Incubator) L’API ScopedValue tente de remédier à ces inconvénients Mais cela présente plusieurs risques : Mutable, fuite de mémoire, consommation de ressources, Stocker et de partager des données immuables Pour une durée de vie limitée à des traitements du thread qui les a écrits public final static ScopedValue<String> VALEUR = ScopedValue.newInstance(); Création d’une instance généralement statique
  • 39. Devoxx France 2023 Sciam where() pour définir une valeur, chainable pour plusieurs valeurs Scoped values (Incubator) 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(TestScopedValue::traiter); get() pour obtenir la valeur ou lève une NoSuchElementException isBound() pour savoir si une valeur est associée au thread System.out.println((VALEUR.isBound() ? VALEUR.get() : "non definie")); Exécuter une tâche dans le thread courant
  • 40. Devoxx France 2023 Sciam Réassociation d’une valeur pour un traitement sous-jacent Scoped values (Incubator) Partage avec les threads virtuels d’une StucturedTaskScope ScopedValue.where(VALEUR, "valeur").run(() -> { afficherValeur(); ScopedValue.where(VALEUR, "autre-valeur") .run(MaClasse::traiter); afficherValeur(); }); ScopedValue.where(VALEUR, "valeur", () -> { try (var scope = new StructuredTaskScope<String>()) { afficherValeur(); scope.fork(MaClasse::traiter); scope.fork(MaClasse::traiter); scope.joinUntil(Instant.now().plusSeconds(10)); } catch (InterruptedException | TimeoutException e) { e.printStackTrace(); } });
  • 41. Devoxx France 2023 Sciam Les autres évolutions Dans les API Dans les outils Concernant la sécurité Concernant la performance
  • 42. Devoxx France 2023 Sciam Java 19, JSR 422 Linux/RISC-V Port Peu d’appareil grand public utilisant RISC-V actuellement Mais cela risque de changer dans un futur proche De nombreux acteurs envisagent son utilisant notamment : Apple, la NASA, de nombreux industriels asiatiques notamment chinois et indiens Anticipe cela avec le portage d’OpenJDK sur Linux/RISC-V Qui est intégré au repository principal RISC-V est une architecture de jeu d'instructions (ISA) RISC libre et gratuite Conçu à l'origine à l'Université Berkeley de Californie Maintenant développé collaborativement sous le parrainage de RISC-V International
  • 43. Devoxx France 2023 Sciam Les autres évolutions Dans les API
  • 44. Devoxx France 2023 Sciam Modification du comportement de méthodes La classe ThreadGroup • destroy() : les invocations sont ignorées • isDaemon() : renvoie la valeur du flag qui n’a plus d’utilité • isDestroyed() : renvoie toujours false • setDaemon() : positionne le flag mais n’a plus aucun effet • suspend(), resume(), stop() : lève une UnsupportedOperationException
  • 45. Devoxx France 2023 Sciam La spécification de ces méthodes est désormais plus stricte Que dans les versions précédentes et la nouvelle implémentation la respecte Double.toString(double) et Float.toString(float) Peuvent retourner des résultats légèrement différents C:java>jshell | Welcome to JShell -- Version 18 | For an introduction type: /help intro jshell> Double.toString(2e23) $1 ==> "1.9999999999999998E23" jshell> Double.toString(1e-323) $2 ==> "1.0E-323" jshell> Double.toString(8.41E21) $4 ==> "8.409999999999999E21" C:java>jshell | Welcome to JShell -- Version 19 | For an introduction type: /help intro jshell> Double.toString(2e23) $1 ==> "2.0E23" jshell> Double.toString(1e-323) $2 ==> "9.9E-324" jshell> Double.toString(8.41E21) $4 ==> "8.41E21"
  • 46. Devoxx France 2023 Sciam Historiquement, 4 styles prédéfinis : FormatStyle.FULL, LONG, MEDIUM et SHORT Formatage de date/heure supplémentaire Possible de spécifier son propre style Qui va tenir compte de la Locale par défaut DateTimeFormatter::ofLocalizedPattern(String) DateTimeFormatterBuilder::appendLocalized(String) septembre 2022 September 2022 DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedPattern("yMMMMM"); LocalDate date = LocalDate.of(2022, 9, 20); System.out.println(date.format(dtf)); Locale.setDefault(Locale.US); dtf = DateTimeFormatter.ofLocalizedPattern("yMMMMM"); System.out.println(date.format(dtf));
  • 47. Devoxx France 2023 Sciam Nouvelles méthodes pour créer des HashMaps et des HashSets Et dérivée dont la taille est préallouée Pouvant accueillir le nombre d’éléments passé en paramètre Sans déclencher un nombre potentiellement important de resize Fabriques pour instancier des HashMaps et HashSets avec une taille préallouée • HashMap.newHashMap(int) • HashSet.newHashSet(int) • LinkedHashMap.newLinkedHashMap(int) • LinkedHashSet.newLinkedHashSet(int) • WeakHashMap.newWeakHashMap(int) A utiliser de préférence à la surcharge des constructeurs Qui attend un paramètre de type int Surtout pour des collections de grandes tailles
  • 48. Devoxx France 2023 Sciam Les autres évolutions Dans les outils
  • 49. Devoxx France 2023 Sciam Dans le JDK 19, javac supporte les versions 7 à 19 incluses Le support de Java 7 par javac C:java>javac -version javac 19 C:java>javac --release=7 Hello.java warning: [options] source value 7 is obsolete and will be removed in a future release warning: [options] target value 7 is obsolete and will be removed in a future release warning: [options] To suppress warnings about obsolete options, use -Xlint:-options. 3 warnings Dans le JDK 20, javac ne supporte plus la version 7 C:java>javac -version javac 20 C:java>javac --release=7 Hello.java error: release version 7 not supported Usage: javac <options> <source files> use --help for a list of possible options
  • 50. Devoxx France 2023 Sciam Nouvel avertissement du compilateur et sont souvent considérées comme équivalentes a += b; a = a + b; short a = 1; int b = 2; a += b; short a = 1; int b = 2; a = a + b; Java 20 : avertissement du compilateur C:java>javac -Xlint Addition2.java Addition2.java:6: warning: [lossy-conversions] implicit cast from int to short in compound assignment is possibly lossy a += b; ^ 1 warning C:java>javac Addition1.java Addition1.java:6: error: incompatible types: possible lossy conversion from int to short a = a + b; ^ 1 error 6: iadd 7: i2s 8: istore_1 C:java>javac Addition2.java C:java>
  • 51. Devoxx France 2023 Sciam JShell affiche les éléments dépréciés de manière singulière Affichage dans JShell Et met en évidence les variables et les mots-clés dans la console
  • 52. Devoxx France 2023 Sciam Syntaxe de recherche a été améliorée Pour permettre la recherche de plusieurs termes Recherche dans la Javadoc
  • 53. Devoxx France 2023 Sciam Les autres évolutions Concernant la sécurité
  • 54. Devoxx France 2023 Sciam Un renforcement de la sécurité par défaut de la plate-forme Java La sécurité Des performances de TLS améliorées L'ajout au KeyStore Du support pour accéder aux certificats de la machine locale sous Windows Le support des CBT Pour l'authentification Negotiate/Kerberos sur HTTPS Java 19 Java 20 DTLS 1.0 est désactivé par défaut Algorithmes EDCH de TLS sont désactivés par défaut
  • 55. Devoxx France 2023 Sciam Les autres évolutions Concernant la performance
  • 56. Devoxx France 2023 Sciam Java 19 Les améliorations de performance Java 20 Génération automatique de l’archive AppCDS avec une seule option +XX:AutoCreateSharedArchive et +XX:SharedArchiveFile=mon-app.jsa Améliorations dans le ramasse-miettes G1 Nouveaux intrinsics pour x86_64 et aarch64 pour différents algorithmes : Chacha20, Poly1305, MD5, …
  • 58. Devoxx France 2023 Sciam Java poursuit son évolution en respectant son modèle de releases Conclusion Cela permettra à Java de rester pertinent aujourd’hui et demain Concernant la syntaxe, particulièrement le pattern matching Java 19 et 20 proposent des fonctionnalités en preview ou incubation Concernant une meilleure utilisation du matériel moderne Concernant la programmation parallèle et concurrente Et de nombreuses améliorations relatives À la performances À la sécurité Aux API À l’outillage
  • 59. Devoxx France 2023 Sciam N’hésitez pas à télécharger et tester une distribution du JDK 20 Auprès d’un fournisseur : Conclusion Java 21 en septembre 2023 Pour anticiper la release de la prochaine version LTS de Java Temurin (Eclipse Adoptium) : https://adoptium.net/temurin/releases/?version=20 Liberica (BellSoft) : https://bell-sw.com/libericajdk/ Oracle OpenJDK (Oracle) : https://jdk.java.net/20/ SapMachine (SAP) : https://sap.github.io/SapMachine/ Zulu (Azul) : https://www.azul.com/downloads/zulu-community/ Corretto (Amazon) : https://aws.amazon.com/fr/corretto/ (Java 19 actuellement) Dans laquelle plusieurs fonctionnalités En preview ou incubation depuis plusieurs semestres Pourraient devenir standards
  • 60. Devoxx France 2023 Sciam Merci pour votre attention