Astuces de débogage IntelliJ

1. Vue d'ensemble

Dans ce didacticiel, nous examinerons certaines fonctionnalités de débogage avancées d'IntelliJ .

On suppose que les bases du débogage sont déjà connues (comment démarrer le débogage, pas à pas , pas à pas , etc.). Sinon, veuillez vous référer à cet article pour plus de détails à ce sujet.

2. Smart Step Into

Il existe des situations où plusieurs méthodes sont appelées sur une seule ligne de code source, comme doJob (getArg1 (), getArg2 ()) . Si nous appelons l' action Step Into (F7), le débogueur entre dans les méthodes dans l'ordre utilisé par la JVM pour l'évaluation: getArg1 - getArg2 - doJob .

Cependant, nous pourrions vouloir ignorer toutes les invocations intermédiaires et passer directement à la méthode cible . L' action Smart Step Into permet de le faire.

Il est lié par défaut à Shift + F7 et ressemble à ceci lorsqu'il est appelé:

Nous pouvons maintenant choisir la méthode cible pour continuer. Notez également qu'IntelliJ place toujours la méthode la plus externe en haut de la liste. Cela signifie que nous pouvons y accéder rapidement en appuyant sur Maj + F7 | Entrez .

3. Drop Frame

Nous pouvons réaliser que certains traitements qui nous intéressent ont déjà eu lieu (par exemple, le calcul de l'argument de la méthode actuelle). Dans ce cas, il est possible de supprimer le ou les cadres actuels de la pile JVM afin de les retraiter.

Considérez la situation suivante:

Supposons que nous soyons intéressés par le débogage du traitement getArg1 , nous supprimons donc l'image actuelle ( méthode doJob ):

Nous sommes maintenant dans la méthode précédente :

Cependant, les arguments d'appel sont déjà calculés à ce stade, nous devons donc également supprimer l'image actuelle :

Nous pouvons maintenant relancer le traitement en appelant Step Into .

4. Points d'arrêt sur le terrain

Parfois, les champs non privés sont modifiés par d'autres classes, non pas via des setters mais directement (c'est le cas avec des bibliothèques tierces où nous ne contrôlons pas le code source).

Dans de telles situations, il peut être difficile de comprendre quand la modification est effectuée. IntelliJ permet de créer des points d'arrêt au niveau du champ pour suivre cela.

Ils sont définis comme d'habitude - cliquez avec le bouton gauche sur la gouttière gauche de l'éditeur sur la ligne de champ. Après cela, il est possible d' ouvrir les propriétés du point d'arrêt (cliquez avec le bouton droit sur la marque du point d'arrêt) et de configurer si nous sommes intéressés par les lectures, les écritures ou les deux du champ :

5. Journalisation des points d'arrêt

Parfois, nous savons qu'il existe une condition de concurrence dans l'application, mais nous ne savons pas où elle se trouve exactement. Cela peut être un défi de le clouer, en particulier lorsque vous travaillez avec un nouveau code.

Nous pouvons ajouter des instructions de débogage aux sources de notre programme. Cependant, une telle capacité n'existe pas pour les bibliothèques tierces.

L'EDI peut vous aider ici - il permet de définir des points d'arrêt qui ne bloquent pas l'exécution une fois frappés, mais produisent des instructions de journalisation à la place .

Prenons l'exemple suivant:

public static void main(String[] args) { ThreadLocalRandom random = ThreadLocalRandom.current(); int count = 0; for (int i = 0; i < 5; i++) { if (isInterested(random.nextInt(10))) { count++; } } System.out.printf("Found %d interested values%n", count); } private static boolean isInterested(int i) { return i % 2 == 0; }

Supposons que nous soyons intéressés par la journalisation des paramètres réels de l' appel isInterested .

Créons un point d'arrêt non bloquant dans la méthode cible ( Maj + clic gauche sur la gouttière gauche de l'éditeur). Après cela, ouvrons ses propriétés (clic droit sur le point d'arrêt) et définissons l'expression cible à journaliser :

Lors de l'exécution de l'application (notez qu'il est toujours nécessaire d'utiliser le mode Debug), nous verrons la sortie:

isInterested(1) isInterested(4) isInterested(3) isInterested(1) isInterested(6) Found 2 interested values

6. Points d'arrêt conditionnels

Nous pouvons avoir une situation où une méthode particulière est appelée à partir de plusieurs threads simultanément et nous devons déboguer le traitement uniquement pour un argument particulier.

IntelliJ permet de créer des points d'arrêt qui interrompent l'exécution uniquement si une condition définie par l'utilisateur est satisfaite .

Voici un exemple qui utilise le code source ci-dessus:

Désormais, le débogueur s'arrêtera sur le point d'arrêt uniquement si l'argument donné est supérieur à 3.

7. Marques d'objets

Il s'agit de la fonctionnalité IntelliJ la plus puissante et la moins connue. C'est assez simple dans l'essence - nous pouvons attacher des étiquettes personnalisées aux objets JVM .

Jetons un coup d'œil à une application que nous utiliserons pour les démontrer:

public class Test { public static void main(String[] args) { Collection tasks = Arrays.asList(new Task(), new Task()); tasks.forEach(task -> new Thread(task).start()); } private static void mayBeAdd(Collection holder) { int i = ThreadLocalRandom.current().nextInt(10); if (i % 3 == 0) { holder.add(i); } } private static class Task implements Runnable { private final Collection holder = new ArrayList(); @Override public void run() { for (int i = 0; i < 20; i++) { mayBeAdd(holder); } } } }

7.1. Créer des marques

Un objet peut être marqué lorsqu'une application est arrêtée sur un point d'arrêt et que la cible est accessible à partir de cadres de pile.

Sélectionnez-le, appuyez sur F11 ( action Marquer l'objet ) et définissez le nom de la cible:

7.2. Afficher les marques

Nous pouvons maintenant voir nos étiquettes d'objet personnalisées même dans d'autres parties de l'application:

Ce qui est cool, c'est que même si un objet marqué n'est pas accessible à partir des cadres de pile pour le moment, nous pouvons toujours voir son état - ouvrez une boîte de dialogue Evaluer l'expression ou ajoutez une nouvelle montre et commencez à taper le nom de la marque.

IntelliJ propose de le compléter avec le suffixe _DebugLabel :

Lorsque nous l'évaluons, l'état de l'objet cible est affiché:

7.3. Marques comme conditions

Il est également possible d'utiliser des marques dans des conditions de point d'arrêt:

8. Conclusion

Nous avons vérifié un certain nombre de techniques qui augmentent considérablement la productivité lors du débogage d'une application multithread.

Il s'agit généralement d'une tâche difficile, et nous ne pouvons pas sous-estimer l'importance de l'aide de l'outillage ici.