I. Introduction▲
Si vous avez déjà utilisé System.out.println
(
) pour déboguer votre code, cet article est à lire absolument.
Un débogueur est un outil que vous pouvez utiliser pour exécuter votre code dans un environnement strictement contrôlé. Il vous permet d'examiner et d'analyser l'état interne de votre application afin de trouver et de corriger les bugs potentiellement cachés au plus profond de votre code.
Avec un débogueur, vous pouvez aussi changer et tester le comportement de votre code sans modifier la source, et faire bien d'autres choses encore. Nous vous invitons à faire vos premiers pas dans le monde du débogage avec nous et à découvrir tout ce qu'un débogueur peut vous apporter.
Cliquez pour lire la vidéo
II. Exécuter du code en mode débogage▲
Démarrer un débogueur pour une application de console est simple. Utilisons l'exemple de code suivant pour illustrer cela :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
package
com.jetbrains;
import
java.io.IOException;
import
java.util.ArrayList;
import
java.util.List;
public
class
CoordinatesCopy {
public
static
void
main
(
String[] args) throws
IOException {
List<
Point>
lineCoordinates =
createCoordinateList
(
);
outputValues
(
lineCoordinates);
Point p =
new
Point
(
13
, 30
);
removeValue
(
lineCoordinates, p);
outputValues
(
lineCoordinates);
}
private
static
void
outputValues
(
List<
Point>
lineCoordinates) {
System.out.println
(
"Output values..."
);
for
(
Point p : lineCoordinates) {
System.out.println
(
p);
}
}
private
static
void
removeValue
(
List<
Point>
lineCoordinates, Point p) {
lineCoordinates.remove
(
p);
}
private
static
List<
Point>
createCoordinateList
(
) {
ArrayList<
Point>
list =
new
ArrayList<>(
);
list.add
(
new
Point
(
12
, 20
));
list.add
(
new
Point
(
13
, 30
));
return
list;
}
}
Il y a plusieurs façons de démarrer le débogueur :
- Vous pouvez cliquer sur l'icône d'exécution dans la zone de la gouttière et sélectionner l'option Debug ;
- Vous pouvez appeler des actions contextuelles sur la classe ou la méthode principale en utilisant Alt+Entrée et en choisissant l'action Debug ;
- Vous pouvez également le lancer à partir du menu d'exécution Run ou en appuyant sur Maj+F9.
Vous pouvez modifier la configuration d'exécution pour ajouter des options de machine virtuelle ou pour passer des arguments au programme.
III. Mettre en pause, reprendre, redémarrer ou arrêter le débogage▲
Si votre application ne répond plus, vous pouvez mettre le programme en pause pour analyser l'endroit où votre code est bloqué. Modifions la méthode principale de la section précédente de la manière suivante :
2.
3.
4.
5.
6.
7.
8.
public
static
void
main
(
String[] args) throws
IOException {
List<
Point>
lineCoordinates =
createCoordinateList
(
);
outputValues
(
lineCoordinates);
Point p =
new
Point
(
13
, 30
);
int
y =
System.in.read
(
); // l'exécution s'arrête ici
removeValue
(
lineCoordinates, p);
outputValues
(
lineCoordinates);
}
Exécutez votre application en mode débogage. Si vous n'entrez pas de valeur, votre application semblera ne plus répondre. Cela est peut-être facile à comprendre dans ce code, mais toutes les bases de code ne sont pas aussi simples.
Dans la fenêtre Debug, cliquez sur Pause Program et la fenêtre de l'éditeur affichera la classe et la méthode que votre application est en train d'exécuter ou sur laquelle elle est bloquée. Dans cet exemple, vous pouvez voir que le code est bloqué pour la saisie de l'utilisateur, indiquant la classe et la méthode pertinentes dans l'éditeur. Vous pouvez également consulter la pile des appels. En cliquant sur les appels de méthode dans la pile des appels, vous visualiserez la classe et la méthode correspondantes dans la fenêtre de l'éditeur.
Pour reprendre l'exécution du programme, cliquez sur Resume Program ou utilisez le raccourci F9. Pour redémarrer le programme en mode débogage, sélectionnez Rerun. Vous pouvez arrêter le débogage de votre programme à tout moment en utilisant l'icône Stop.
Notez que je n'ai fixé aucun point d'arrêt dans ce cas.
IV. Points d'arrêt▲
Un point d'arrêt arrêtera l'exécution de votre programme et vous pourrez analyser l'état de votre code.
Pour fixer un point d'arrêt sur une ligne de code, cliquez dans la zone de la gouttière ou utilisez le raccourci Ctrl+F8 (Win/Linux) ou ⌘ F8 (macOS). Si vous ne voulez pas arrêter l'exécution chaque fois qu'elle atteint un point d'arrêt, vous pouvez définir une condition pour le point d'arrêt. Par exemple, ajoutons un point d'arrêt dans la méthode outputValues(), sur la ligne de code qui génère la valeur de variable p et définissons une condition pour arrêter l'exécution du code lorsque le champ y de la variable de référence p est égal à 30.
Vous pouvez également faire glisser et déposer le point d'arrêt dans la gouttière et le déplacer vers une autre ligne de code. Par défaut, un clic sur l'icône d'un point d'arrêt dans la gouttière le supprime (vous pouvez modifier ce comportement par défaut dans Settings | Preferences). Mais si vous avez défini des conditions ou d'autres paramètres pour un point d'arrêt, vous préférerez peut-être qu'il soit désactivé plutôt que supprimé lorsque vous cliquez dessus. Dans ce cas, vous pouvez faire un clic droit sur l'icône du point d'arrêt et en sélectionner Disable. Une coche indique qu'il y a des informations pour cette ligne de code, tandis qu'une croix indique qu'il n'y a aucune information sur ce point d'arrêt.
Pour vérifier le fonctionnement du point d'arrêt et de ses conditions, exécutez l'exemple de code inclus dans cet article (en mode débogage). Vous verrez que ce programme s'arrêtera lorsque la valeur du champ y pour la variable p sera de 30.
Les points d'arrêt offrent bien plus que cela. Faites un clic droit sur l'icône de point d'arrêt dans la gouttière et cliquez sur More. Dans la boîte de dialogue qui s'ouvre, vous pouvez modifier un point d'arrêt afin qu'il ne suspende pas l'exécution du programme et qu'il enregistre plutôt une expression lorsqu'il est atteint. Enregistrons la valeur des champs x et y de la classe Point et relançons notre code. L'exécution du code ne s'arrête pas au point d'arrêt, mais enregistre l'expression que nous avons définie dans la console.
V. Fenêtre de débogage▲
La fenêtre de débogage affiche des informations importantes lorsque votre application suspend son exécution sur un point d'arrêt, comme les cadres, les threads, la fenêtre de la console, les icônes des step actions, le volet des variables, et bien plus encore :
Si vous fermez la fenêtre de débogage par erreur, vous pouvez toujours la rouvrir en utilisant le raccourci Alt+5 (Win/Linux) ou ⌘ 5 (macOS). Il y a plusieurs façons d'accéder à la fenêtre de débogage. Vous pouvez également y accéder avec la fonctionnalité « Search everywhere » (raccourci : Maj+Maj), en utilisant Find Action (raccourci : Ctrl+Maj+A pour Win/Linux et ⇧ ⌘ A pour macOS) et en recherchant « Debug ».
Vous pouvez aussi afficher la fenêtre de débogage une fois que votre application a fini de s'exécuter en mode débogage. La fenêtre de débogage peut servir non seulement à naviguer dans le code en mode débogage, mais aussi à visualiser tous les points d'arrêt de votre programme, à les désactiver et à modifier davantage leur comportement.
Avant de passer aux step actions qui sont utilisées pour déboguer une application, examinons l'exemple d'application utilisé ci-dessous.
VI. Présentation de l'exemple d'application▲
Le code utilisé dans cet article est simple. La méthode createCoOrdinateList
(
) crée deux instances de la classe Point et les ajoute à une ArrayList. La classe Point comporte deux champs, x et y, et des méthodes getter et setter. La méthode outputValues
(
) génère les éléments de liste passés à la console. La ligne de code suivante crée une instance Point et la méthode removeValue
(
) tente de la supprimer de la liste lineCoordinates.
Lorsque vous exécutez ce code, vous constaterez dans la sortie que même si un Point avec des valeurs x et y a été ajouté à la liste, lorsqu'une autre instance avec des valeurs identiques a été créée pour le supprimer, cela a échoué. Déboguons le code.
Pour déboguer votre code, vous devez connaître les différentes step actions pour vous déplacer dans votre code et identifier les bogues.
VII. Step actions▲
Il existe différentes façons de naviguer dans votre code en mode débogage. Par exemple, vous pouvez choisir d'exécuter une ligne de code sans vous préoccuper des détails des méthodes appelées. Vous pouvez également choisir de voir quelles lignes de code s'exécutent lorsque vous appelez une autre méthode à partir de votre application, de vos bibliothèques ou de vos API. Vous pouvez l'effectuer à travers les différentes step actions.
Définissez un point d'arrêt avant de lancer l'application en mode débogage. Les différentes step actions sont :
- Step Over (F8) vous permet d'exécuter une ligne de code et de passer à la ligne suivante. En parcourant le code, vous verrez la valeur des variables à côté du code dans la fenêtre de l'éditeur. Ces valeurs sont également visibles dans le volet Variables de la fenêtre de débogage ;
- Step Into (F7) vous amène à la première ligne de code dans une méthode définie dans la même classe ou une autre classe dans l'application ;
- Force Step Into vous permet de déboguer les méthodes définies dans les API ou les bibliothèques. Si le code source de l'API ou de la bibliothèque n'est pas disponible, IntelliJ IDEA le décompile et le débogue pour vous ;
- avec Step Out, vous pouvez arrêter de parcourir le code ligne par ligne et revenir à la méthode d'appel. La méthode appelée s'exécute, mais sans parcourir chaque ligne de code qu'elle contient ;
- Drop Frame vous permet de revenir en arrière dans l'exécution du code en supprimant un appel de méthode.
Utilisons toutes les actions précédentes pour déboguer la classe Coordinates. Nous commencerons par effectuer un step over des lignes de code dans la méthode main
(
) , puis un step into dans la méthode removeValues
(
), et un force step into dans la méthode remove
(
) de la classe ArrayList et de la méthode equals
(
) pour vérifier comment les valeurs de la liste lineCoordinates sont comparées à la valeur de la variable de référence p, afin qu'une valeur correspondante puisse être enlevée de la liste. Si vous avancez à une ligne de code pendant le débogage, vous pouvez utiliser Drop Frame pour supprimer une trame de la pile des appels et revenir à la méthode d'appel.
Dans l'exemple d'application, nous avons découvert que le bug est causé par la façon dont la méthode equals
(
) compare les valeurs. Elle renvoie la valeur « true » uniquement si les références correspondent et non si les valeurs des champs concernés correspondent.
Corrigeons ce bogue en remplaçant la méthode equals
(
) dans la classe Point.
Maintenant, exécutons à nouveau le code et vérifions s'il fonctionne comme prévu. Démarrez l'application et voyez le résultat.
Tout semble fonctionner correctement. Nous avons réussi à trouver un bogue et à le corriger !
Si vous passez d'une classe à l'autre et que vous lisez du code et avez manqué l'endroit où il s'exécute, vous pouvez cliquer sur Show Execution Point. Si vous ne voulez pas attendre l’exécution du code ligne par ligne, vous pouvez avancer d'une ligne et cliquer sur Run to Cursor.
VIII. Volet Variables▲
Le débogueur inline est très utile, car il indique la valeur des variables dans l'éditeur au fur et à mesure que vous avancez dans le code. Cependant, le volet Variables fournit beaucoup plus de détails.
Dans cet exemple, comme nous n'avons pas remplacé la méthode toString() par la classe Point, la fenêtre de l'éditeur affiche le nom de la classe et l'identifiant de l'objet de débogage, ce qui ne semble pas très utile. Le volet de débogage affiche tous les champs de variables, y compris les champs privés.
Cliquez sur les piles pour afficher les variables qui s'y rapportent.
Vous pouvez faire un clic droit sur une variable et sélectionner Jump To Source (F4) pour voir où elle a été déclarée et mieux comprendre votre code. En sélectionnant l'option Jump To Type Source (Shift+F4), vous pouvez également voir la définition des variables non primitives.
Dans une pile d'appels, vous avez la possibilité d'évaluer une expression pour vérifier vos hypothèses. Par exemple, il est possible d'évaluer la valeur de la variable this, ou d'autres expressions valides, comme this est doublement égale à une instance de la classe Point ou this est .equals() à une instance de la classe Point.
Vous pouvez créer une variable dont la valeur est accessible dans toutes les piles d'appels en ajoutant une nouvelle surveillance (watch). Disons, System.getProperty, et utilisez le nom de votre système d'exploitation.
Vous pouvez créer des surveillances pour voir la valeur de certaines variables dans toutes les piles d'appels. Il existe de multiples façons de le faire. Vous pouvez faire un clic droit sur le code dans l'éditeur et sélectionner Add to watches. Dans le volet Variable, vous pouvez également cliquer sur la variable, la faire glisser et la déposer dans le volet Watches.
Il est possible que les valeurs de ces variables ne soient pas disponibles dans toutes les piles d'appels. Cela dépend vraiment de la portée de la variable.
IX. Modifier le comportement du code▲
Saviez-vous que vous pouvez modifier le comportement de votre code sans changer sa source ? Et cela s'applique également au code défini par une autre API ou un autre framework.
Dans cette exécution de code, les champs x et y des instances Point comparées sont égaux et cette méthode equals
(
) est sur le point de renvoyer la valeur « true ». Nous pouvons changer la valeur d'une variable en faisant un clic droit sur celle-ci dans le volet des variables et en sélectionnant Set Value… Lorsque nous faisons cela, le comportement du code change. Avec la valeur modifiée, la méthode equals
(
) renvoie « false » et cette valeur ne sera pas retirée du ArrayList.
X. En résumé▲
Le débogueur est un outil puissant et polyvalent qui exécute des programmes dans un environnement contrôlé. Avec un débogueur, vous pouvez voir l'état interne d'une application, trouver des bugs, comprendre le code et bien d'autres choses.
Ne manquez pas notre prochain article dans lequel nous aborderons des fonctionnalités avancées comme le débogage à distance, les types de points d'arrêt, l'exécution de tests jusqu'à ce qu'ils échouent, et bien plus encore.
XI. Remerciements Developpez.com▲
Nous tenons à remercier Malick pour la mise au gabarit et Claude Leloup pour la relecture orthographique.