Astuces de débogage IntelliJ

Astuces de débogage IntelliJ

1. Vue d'ensemble

Dans ce didacticiel, nous examinerons quelquesadvanced IntelliJ debugging facilities.

Il est supposé que les bases du débogage sont déjà connues (comment démarrer le débogage,Step Into, actionsStep Over, etc.). Sinon, veuillez vous référer àthis 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, commedoJob(getArg1(), getArg2()). Si nous appelons l'actionStep Into (F7), le débogueur entre dans les méthodes dans l'ordre utilisé par la JVM pour l'évaluation:getArg1 -getArg2 -doJob.

Cependant,we might want to skip all intermediate invocations and proceed to the target method directly. L'actionSmart Step Into permet de faire cela.

C'estbound to the Shift + F7 by default et ressemble à ceci lorsqu'il est appelé:

image

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

3. Châssis de baisse

Nous pouvons réaliser que certains traitements qui nous intéressent ont déjà eu lieu (par exemple calcul de l'argument de la méthode actuelle). Dans ce cas,it’s possible to drop the current JVM stack frame(s) in order to re-process them.

Considérez la situation suivante:

image

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

image

Maintenantwe’re in the previous method:

image

Cependant, les arguments d'appel sont déjà calculés à ce stade, donc,we need to drop the current frame as well:

image

Nous pouvons maintenant relancer le traitement en appelantStep Into.

4. Points de rupture de champ

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 faite. IntelliJ permet de créer des points d'arrêt au niveau du champ pour suivre cela.

Ils sont configurés comme d'habitude - faites un clic gauche sur la gouttière de l'éditeur gauche sur la ligne du champ. Après cela, il est possible deopen breakpoint properties (right-click on the breakpoint mark) and configure if we’re interested in the field’s reads, writes, or both:

image

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. Il peut être difficile de s’y attaquer, surtout lorsqu’on travaille 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'IDE peut aider ici -it allows setting breakpoints that don’t block execution once hit, but produce logging statements instead.

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 souhaitons enregistrer les paramètres réels de l'appelisInterested.

Créons un point d'arrêt non bloquant dans la méthode cible (Shift + 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) etdefine the target expression to log:

image

Lors de l'exécution de l'application (notez qu'il est toujours nécessaire d'utiliser le mode Débogage), nous verrons le résultat:

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 autorisecreating breakpoints that pause the execution only if a user-defined condition is satisfied.

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

imageimage

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

C'est la fonctionnalité IntelliJ la plus puissante et la moins connue. C’est assez simple dans l’essence -we can attach custom labels to JVM objects.

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 surF11 (actionMark Object) et définissez le nom de la cible:

image

7.2. Afficher les marques

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

imageimage

Ce qui est cool, c'est queeven if a marked object is not reachable from stack frames at the moment, we can still see its state - ouvre une boîte de dialogueEvaluate Expression ou ajoute une nouvelle montre et commence à taper le nom de la marque.

IntelliJ propose de le compléter avec le suffixe_DebugLabel:

imageimage

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

imageimage

7.3. Marques comme conditions

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

imageimage

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.

C’est généralement une tâche difficile, et nous ne pouvons pas sous-estimer l’importance de l’aide des outils ici.