Aller au contenu

Guides

Passer une application Java 8 critique à un Java moderne

· 6 min de lecture

Mettez à niveau une application Java 8 critique par étapes : inventoriez chaque dépendance, passez d'abord à Java 11, puis à chaque version à support long terme suivante, et laissez les tests et les tests de charge décider du moment où chaque étape est sûre. L'essentiel du travail se situe dans les bibliothèques, l'outillage de build et le code qui touche aux éléments internes du JDK, pas dans votre logique métier.

Rester sur Java 8 réduit vos options chaque année

Une application Java 8 peut continuer à tourner des années, et c'est bien là le piège. Les correctifs de sécurité dépendent de plus en plus d'un contrat de support payant ou d'une distribution qui les rétroporte encore, et les grandes bibliothèques sont passées à autre chose. Spring Boot 3, par exemple, exige au minimum Java 17 : rester sur Java 8 fige donc aussi vos versions de framework.

Les JVM récentes exécutent aussi mieux le même code. G1 est le ramasse-miettes par défaut depuis Java 9, des ramasse-miettes à faible pause comme ZGC sont prêts pour la production, et les compact strings réduisent l'utilisation mémoire des charges de travail riches en texte. Les ingénieurs attendent aussi des fonctionnalités modernes du langage, comme les records, les text blocks et les expressions switch, ce qui rend plus difficile le recrutement sur une base de code Java 8.

Commencez par inventorier tout ce dont l'application dépend

La mise à niveau du JDK elle-même est rarement la partie difficile. La difficulté, c'est la longue traîne de bibliothèques, plugins et agents écrits pour Java 8 et jamais mis à jour. Dressez une liste complète avant de changer quoi que ce soit, et notez la version de chaque élément.

  • L'éditeur et la version du JDK dans chaque environnement, des postes des développeurs à la production.
  • Les dépendances directes et transitives, exportées depuis l'arbre de dépendances Maven ou le rapport de dépendances Gradle.
  • Les plugins de build, les générateurs de code et les processeurs d'annotations comme Lombok.
  • Le serveur d'applications ou le conteneur de servlets, si l'application tourne dans l'un d'eux.
  • Les agents Java de supervision, de profilage ou de sécurité, qui s'accrochent profondément à la JVM.
  • Le code qui utilise des API internes du JDK, repéré avec l'outil jdeps et son option jdk-internals.
  • Les options de la JVM, les réglages du ramasse-miettes et tout script qui analyse la sortie de java -version.

Passez d'une version à support long terme à l'autre au lieu de sauter

Passez de Java 8 à 11, puis à 17, puis à 21 ou 25. Chaque étape a ses propres suppressions et changements de comportement, et un saut unique les mélange tous en une seule panne impossible à diagnostiquer. Corriger une couche à la fois garde chaque étape assez petite pour être relue et annulée.

Quand c'est possible, mettez à niveau les bibliothèques en restant sur Java 8, car beaucoup de versions récentes prennent en charge à la fois les anciens et les nouveaux JDK. Exécutez ensuite le build existant sur la nouvelle JVM avant de changer la cible de compilation. Cela sépare les problèmes d'exécution des problèmes de compilation, et l'option de compilation release garde la cible de bytecode explicite.

Faites de la suite de tests le verrou de chaque étape

Les tests sont votre seul signal objectif que l'application mise à niveau se comporte toujours de la même façon. Si les chemins critiques sont peu couverts, écrivez d'abord des tests de caractérisation : des tests qui capturent ce que fait le système aujourd'hui, y compris ses cas limites étranges, sans juger si ce comportement est correct.

Ajoutez des tests d'intégration qui s'exécutent sur une vraie base de données et de vrais brokers de messages, car beaucoup d'échecs de mise à niveau n'apparaissent qu'à ces frontières. Pour les systèmes riches en calculs, rejouez les mêmes entrées dans l'ancienne et la nouvelle version et comparez les sorties champ par champ. Faites attention aux dates, aux nombres et au texte : Java 9 est passé par défaut aux données de locale CLDR et Java 18 a fait d'UTF-8 le jeu de caractères par défaut, et les deux peuvent modifier silencieusement le formatage ou l'analyse.

Connaissez les pièges qui cassent le code Java 8

La plupart des régressions entrent dans quelques catégories connues. Recherchez chacune d'elles avant la mise à niveau au lieu de la découvrir en production.

  • Modules Java EE et CORBA supprimés : Java 11 a retiré du JDK JAXB, JAX-WS, JavaBeans Activation et les annotations communes, qui doivent donc être réintégrés comme dépendances explicites.
  • Encapsulation forte des éléments internes du JDK : l'accès réflexif illégal produisait des avertissements depuis Java 9, il est refusé par défaut depuis Java 16 et ne peut plus être réactivé globalement depuis Java 17. Corrigez-le en mettant à niveau la bibliothèque ; n'utilisez add-opens que comme exception temporaire et documentée.
  • Outils de bytecode obsolètes : les anciennes versions de Lombok, Mockito, Byte Buddy, ASM et des plugins de build échouent sur les versions de fichiers de classe plus récentes.
  • Fonctionnalités supprimées : le moteur JavaScript Nashorn a été supprimé dans Java 15, et le Security Manager a été déprécié dans Java 17 puis définitivement désactivé dans Java 24.
  • Options de JVM supprimées : le ramasse-miettes CMS a été supprimé dans Java 14, et une JVM lancée avec des options supprimées peut refuser de démarrer.

Prouvez les performances sous une charge réaliste, pas sur un portable

Un nouveau JDK change le ramasse-miettes, le compilateur JIT et l'organisation de la mémoire : les performances peuvent donc évoluer dans un sens comme dans l'autre. Lancez un test de charge qui reproduit le profil de trafic de production, sur le même matériel ou le même type d'instance, avant et après chaque étape. Comparez les percentiles de latence, le débit, la mémoire et les pauses du ramasse-miettes, et laissez le JIT chauffer avant de mesurer.

Nos ingénieurs ont mené, via Sopra Steria, la migration de Java 8 à 16 d'une application critique de négoce de gaz intrajournalier pour une salle de marché gazière nationale. Sur ce système, les calculs de capacité et de flux énergétiques devaient rester justes et rapides sous une charge à haute fréquence : la mise à niveau s'est donc accompagnée d'un travail d'optimisation de ces calculs et a été validée sous charge plutôt que supposée.

Déployez progressivement et gardez une voie de retour

Déployez d'abord l'environnement d'exécution mis à niveau sur une seule instance ou une petite part du trafic, et surveillez les taux d'erreur, la latence et le comportement du ramasse-miettes par rapport à la référence Java 8. Gardez le build précédent déployable jusqu'à ce que la nouvelle version ait traversé des cycles d'activité normaux, y compris les fins de mois ou les périodes de pointe.

Seulement alors, supprimez les artefacts Java 8 et commencez à utiliser les nouvelles fonctionnalités du langage. Si vous voulez de l'aide pour planifier ou mener une mise à niveau de ce type, SDK Enterprises y affecte des ingénieurs internes et des spécialistes sélectionnés, sous un seul contrat dont nous sommes responsables.

À retenir

  • L'effort d'une mise à niveau Java 8 se concentre surtout sur les dépendances, l'outillage de build et l'utilisation des éléments internes du JDK, pas sur la logique métier.
  • Passez les versions à support long terme une à une pour que chaque échec ait une cause unique et identifiable.
  • Les tests de caractérisation et d'intégration sont le verrou de chaque étape, en particulier pour les dates, les nombres et l'encodage du texte.
  • Validez les performances sous une charge proche de la production, car les changements du ramasse-miettes et du JIT peuvent faire varier les résultats dans les deux sens.
  • Déployez d'abord sur une petite part du trafic et gardez le build Java 8 déployable tant que le nouvel environnement n'a pas fait ses preuves.

FAQ

Peut-on passer directement de Java 8 à Java 21 ?

C'est possible, mais vous héritez d'un coup de tous les changements de Java 9 à 21, ce qui rend les échecs difficiles à retracer. Passer par 11 et 17 coûte un peu plus de temps de build et épargne beaucoup de débogage sur un système critique.

Combien de temps prend une mise à niveau depuis Java 8 ?

Cela dépend du nombre de dépendances, du nombre de celles qui utilisent des éléments internes du JDK, de la couverture de tests et de l'ampleur des tests de charge nécessaires. Un inventaire et un essai sur la nouvelle JVM vous donnent tôt une estimation réaliste, avant de vous engager sur un calendrier.

Faut-il réécrire le code pour utiliser les nouvelles fonctionnalités de Java ?

Non. Java conserve une forte compatibilité ascendante pour le code qui s'en tient aux API standard et non dépréciées. Adoptez les records, les text blocks et les autres fonctionnalités progressivement, une fois le nouvel environnement d'exécution stable en production.

Dites-nous ce dont vous avez besoin.

Quelque chose à créer, des personnes à trouver ou une question à trancher. En 30 minutes d'appel, nous vous écoutons et vous disons franchement comment nous pouvons vous aider, et ce qu'il faudrait prévoir.