Les versions 19 et 20 de Java, publiées en septembre et mars derniers, sont les 10eme et 11eme release en application du modèle de release tous les 6 mois.
En attendant la publication de Java 21, la prochaine version LTS publiée en septembre de cette année, et pour en donner quelques aperçus, cette présentation brosse une revue détaillée des nouveautés introduites dans ces nouvelles versions non-LTS de Java, issues des projets Amber, Panama et Loom d’OpenJDK ainsi que des fonctionnalités non incluses dans des JEPs.
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
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
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
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
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
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
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