Comment Lire et Comprendre la Stacktrace en Java ?
Temps de lecture: 5 minutes
Lorsque quelque chose ne tourne pas rond dans une application Java en cours d'exécution, le premier indice est souvent l'impression de lignes à l'écran qui ressemblent à peu près à ce qui suit :
Ceci est une Stacktrace, et dans ce blog post, je vais vous expliquer de quoi il s'agit, comment ils sont générés et comment les lire et les comprendre. Si ça à déjà l’air pénible, lisez la suite...
Anatomie d'une Stacktrace
Habituellement, une Stacktrace s'affiche lorsqu'une Exception n'est pas gérée correctement dans le code. Il peut s'agir d'un des types d'exception intégrés de base dans Java, ou d'une exception customisée créée par un programme ou une librairie.
La Stacktrace contient le type d'exception et un message, ainsi qu'une liste de tous les appels de méthode qui étaient en cours au moment où l'exception a été levée.
C’est parti pour la dissection de la Stacktrace. La première ligne nous indique les détails de l'exception :
C'est un bon début. La ligne 2 montre quel code était en cours d’exécution lorsque le problème est arrivé :
Ça nous aide à circonscrire le problème, mais quelle partie du code à appelé badMethod
? La réponse se trouve à la ligne suivante, qui peut être lue exactement de la même manière. Et comment en est-on arrivé là ? Regardez sur la ligne suivante. Et ainsi de suite, jusqu'à la dernière ligne, qui est la main method
(méthode principale) de l'application. En lisant la Stacktrace de bas en haut, vous pouvez retracer le chemin exact depuis le début de votre code, jusqu'au moment de l'exception.
Qu'est-ce qui a mal tourné ?
La cause d'une exception est généralement une instruction throw
explicite. En utilisant le nom du fichier et le numéro de ligne, vous pouvez vérifier exactement quel ligne de code a généré l'exception. Cela ressemblera probablement à quelque chose comme ceci :
C'est un bon endroit pour commencer à chercher le problème sous-jacent : y a-t-il des instructions “if” autour de cette ligne ? Que fait ce code ? D'où proviennent les données utilisées dans cette méthode ?
Il est également possible pour le code de lancer une exception sans qu’un throw
explicite soit visible dans le code, par exemple vous pouvez obtenir :
NullPointerException
siobj
estnull
dans le code ce qui appelleobj.someMethod()
ArithmeticException
arrive si on fait une division par zero avec des integers, ex:1/0
. Bizarrement, il n'y a pas d'exception si c'est avec des floats,1.0/0.0
retourneinfinity
sans aucun problème!NullPointerException
si un nombre entiernull
est incrémenté en tant queint
. ex:Integer a=null; a++;
- Il existe d'autres exemples dans la documentation Java, c'est pourquoi il est important de savoir que les exceptions peuvent survenir sans être explicitement codées.
Traitement des exceptions générées par les librairies
L'une des grandes forces de Java est le grand nombre de librairies disponibles. Toute lib populaire sera bien testée donc lorsque vous êtes confrontés à une exception provenant d'une librairie, il est fort probable que l’erreur vienne de la façon dont nous l'utilisons et pas du code de la librairie lui-même.
Par exemple, si nous utilisons la classe Fraction d'Apache Commons Lang et que nous lui passons des paramètres comme suit :
Si numberOfBars
est égal à zéro, la Stacktrace sera comme ça :
Beaucoup de bonnes librairies fournissent une Javadoc qui comprend des informations sur les types d'exceptions qui peuvent être thrown
(levées) et pourquoi. Dans ce cas particulier Fraction.getFraction
a documenté que ça lèvera une ArithmeticException si une fraction a un dénominateur zéro. Ici aussi, le message est clair, mais dans des situations plus complexes ou ambiguës, la doc peut être votre meilleure alliée.
Pour lire cette Stacktrace, commencez en haut avec le type d’Exception - ArithmeticException
et le message message The denominator must not be zero
(Le dénominateur ne doit pas être nul). Cela donne une idée de ce qui a mal tourné, mais pour découvrir le code qui a causé l'exception, parcourez la Stacktrace à la recherche de quelque chose dans le package com.myproject
(c'est à la 3ème ligne ici), puis rendez-vous en fin de la ligne pour voir où se trouve le code (MyProject.java:17)
. Cette ligne contiendra du code qui s’appelle Fraction.getFraction
. C'est le point de départ de l'enquête : qu'est-ce quels sont les paramètres passés à getFraction
? D'où viennent-ils ?
Dans les gros projets comportant de nombreuses dépendances, les Stacktraces peuvent compter des centaines de lignes. Si vous voyez une grosse Stacktrace, entraînez-vous à parcourir la liste des at ... at ... at ...
à la recherche de votre propre code - c'est une compétence utile à développer.
La bonne pratique : intercepter et relever les exceptions
Disons que nous travaillons sur un projet de taille conséquente qui traite des FooBars
fictifs, et que notre code va être utilisé par d'autres. Nous pourrions décider d'interecpter l'ArithmeticException
de Fraction
et la lever nous même comme quelque chose de custom pour notre projet, ce qui donnerait :
Utiliser cette technique présente plusieurs avantages :
- Nos utilisateurs n'ont pas à se préoccuper de la
ArithmeticException
- ce qui nous donne la possibilité de modifier la façon dont commons-lang est utilisé. - Il est possible d'ajouter plus de contexte, en précisant par exemple quel est le nombre de FooBars à l'origine du problème.
- Cela peut aussi rendre les Stacktraces plus faciles à lire, comme nous le verrons ci-dessous.
Il n'est pas nécessaire d’écrire son propre code pour gérer chaque exception, mais lorsqu'il semble y avoir une librairie entre deux couches de code à vous, comme l'appel à une lib, ça a souvent du sens.
Vous pouvez noter que le constructeur de MyProjectFooBarException
prend 2 arguments : un message et l'exception qui l'a provoqué. Chaque exception en Java possède un champ cause
, et lorsque vous interceptez et relevez l’Exception comme ici, vous devriez toujours le remplir pour aider les autres développeurs à déboguer les erreurs. La Stacktrace pourrait ressembler à ce qui suit :
L'exception la plus récente est sur la première ligne, et l'endroit où elle a été levée est toujours sur la ligne 2. Cependant, ce type de Stacktrace peut prêter à confusion car la méthode d’interception a changé l'ordre des appels de méthode par rapport aux Stacktraces que nous avons vus auparavant. La méthode principale n'est plus en bas de la pile, et le code qui a déclenché l'exception en premier lieu n'est plus en haut de la pile. Lorsque vous utilisez cette technique plusieurs fois dans votre code, c’est encore plus visible mais l’idée reste la même:
Vérifiez les sections de la première à la dernière en cherchant votre code, puis lisez les sections pertinentes de bas en haut.
Libraries vs frameworks
La différence entre une lib et un framework en Java est la suivante :
- Votre code appelle des méthodes dans une librairie
- Votre code est appelé par les méthodes d'un Framework
Un type courant de Framework est le serveur d'application web, comme SparkJava ou Spring Boot. En utilisant SparkJava et Commons-Lang, nous pourrions un jour voir une Stacktrace comme celle-ci :
OK, c’est plutôt long. Comme avant, le premier suspect est notre propre code, mais il est de plus en plus difficile de trouver où il se trouve. En haut, il y a l'exception du Framework, en bas celle de la Bibliothèque et au milieu, notre propre code. Ouf !
Un Framework et complexe et une lib peuvent créer une douzaine ou plus de sections Caused by:
(Causé par). Une bonne stratégie est de parcourir ces lignes à la recherche de votre propre code : Caused by: com.myproject...
Lisez ensuite cette section en détail pour isoler le problème.
En résumé
Apprendre à comprendre les Stacktraces et à les lire rapidement vous permettra de localiser les problèmes et rendra le débogage beaucoup moins pénible. C'est une compétence qui s'améliore avec la pratique, alors la prochaine fois que vous verrez une grosse Stacktrace, ne soyez pas intimidé - il y a beaucoup d'informations extrêmement utiles si vous savez comment les lire.
Si vous avez des conseils ou des astuces sur la façon de traiter les Stacktraces Java, je serais ravi de les connaître. N'hésitez pas à me contacter par email : mgilliard@twilio.com.
Articles associés
Ressources connexes
Twilio Docs
Des API aux SDK en passant par les exemples d'applications
Documentation de référence sur l'API, SDK, bibliothèques d'assistance, démarrages rapides et didacticiels pour votre langage et votre plateforme.
Centre de ressources
Les derniers ebooks, rapports de l'industrie et webinaires
Apprenez des experts en engagement client pour améliorer votre propre communication.
Ahoy
Le hub de la communauté des développeurs de Twilio
Meilleures pratiques, exemples de code et inspiration pour créer des expériences de communication et d'engagement numérique.