Introduction
Les StableValue
sont une nouvelle fonctionnalité introduite dans la version preview de la JDK 25, visant à améliorer la gestion des objets immuables en Java. Cette innovation permet de traiter certaines valeurs dynamiques comme des constantes, offrant ainsi des optimisations de performance similaires à celles des champs final
, tout en offrant une plus grande flexibilité quant au moment de leur initialisation.
La JEP liée à cette évolution est la JEP-502, dont les objectifs sont définis ainsi :
- Améliorer le démarrage des applications Java en fragmentant l’initialisation monolithique de l’état de l’application.
- Découpler la création des valeurs stables de leur initialisation, sans pénalités de performance significatives.
- Garantir que les valeurs stables sont initialisées au plus une fois, même dans les programmes multi-threadés.
- Permettre au code utilisateur de bénéficier en toute sécurité des optimisations de constant folding1, au même titre que les variables déclarées
final
Qu’est-ce qu’une Stable Value ?
|
|
Une StableValue
est un objet encapsulant une donnée immuable. Contrairement aux champs final
, qui doivent être initialisés dès la création de l’objet ou de la classe, les Stable Value peuvent être initialisés à la demande, après leur déclaration. Cela signifie qu’ils ne sont définis qu’au moment où leur valeur est nécessaire, ce qui peut améliorer les performances de démarrage des applications Java -en évitant de charger l’état complet de l’application à son démarrage-.
Exemples d’utilisation
Tous les exemples suivants sont tirés de la JavaDoc officielle2.
Voici un exemple simple d’utilisation des StableValue
dans une classe OrderController
.
Version classique :
|
|
Dans cette version, le logger est instancié automatiquement chaque fois qu’une instance de la classe OrderController
est créée. Cela pourrait se traduire par un ralentissement de la création d’une instance de cette classe, puisque l’on peut imaginer que la création de ce logger soit relativement lente (si elle nécessite de lire un fichier de config par exemple, ou de préparer un fichier de sortie pour les logs…)
Version StableValue
|
|
Dans cet exemple, le champ logger
est une StableValue
. Il est initialisé uniquement lorsque la méthode getLogger()
est appelée pour la première fois. Cela permet de retarder l’initialisation coûteuse du logger jusqu’à ce qu’il soit réellement nécessaire.
Fonction stable
Les StableValue
posent les fondations d’abstractions de plus haut niveau. Ainsi, un supplier
permet par exemple de produire une valeur et de mettre en cache son résultat :
|
|
On notera, dans ce cas de figure, l’absence d’accesseur au logger par rapport à l’exemple précédent, ce qui rend son utilisation plus élégante.
Collection stable
De la même façon, il est possible de créer des Collection
stables, dont les valeurs sont calculées lors du premier accès :
|
|
N.B. la JVM transformera directement cette valeur en 16 au bout de quelques cycles d’exécution, grâce au constant folding
Composition
Enfin, il est également possible de faire de la composition de Stable Value, ce qui permet d’évaluer paresseusement des objets :
|
|
L’appel à bar()
créera le singleton Bar
s’il n’est pas déjà créé. Lors de cette création, le dépendant Foo
sera d’abord créé si Foo
n’existe pas déjà.
Thread Safety
Le contenu d’une valeur stable est garanti d’être défini au plus une fois. Si plusieurs threads sont en compétition pour définir une valeur stable, une seule mise à jour réussit (le premier thread qui arrive à initialiser la valeur), tandis que les autres mises à jour sont bloquées jusqu’à ce que la valeur stable soit définie.
Essayer par soi-même
Pour essayer cette fonctionnalité, téléchargez la jdk25 puis compilez et lancer votre programme en activant les preview :
|
|
Conclusion
Les Stable Value représentent un mécanisme particulièrement intéressant dans la gestion des objets immuables en Java. En offrant une initialisation différée et des optimisations de performance, ils permettent aux développeurs de créer des applications plus efficaces et réactives.
Le constant folding avec javac et avec le JIT ↩︎
https://cr.openjdk.org/~pminborg/stable-values2/api/java.base/java/lang/StableValue.html ↩︎