IntelliJ Debugging Tricks

1. Übersicht

In diesem Tutorial werden einige erweiterte IntelliJ-Debugging-Funktionen vorgestellt .

Es wird davon ausgegangen, dass die Grundlagen des Debuggens bereits bekannt sind (wie das Debuggen gestartet wird, Step Into , Step Over- Aktionen usw.). Wenn nicht, lesen Sie bitte diesen Artikel für weitere Details dazu.

2. Smart Step Into

Es gibt Situationen, in denen mehrere Methoden in einer einzigen Zeile des Quellcodes aufgerufen werden, z. B. doJob (getArg1 (), getArg2 ()) . Wenn wir Step Into action (F7) aufrufen , geht der Debugger in der Reihenfolge in die Methoden ein, die von der JVM zur Auswertung verwendet werden: getArg1 - getArg2 - doJob .

Allerdings könnten wir alle Zwischen Anrufungen und fahren Sie mit dem Zielmethode direkt zu überspringen . Smart Step Into Action ermöglicht dies.

Es ist standardmäßig an Umschalt + F7 gebunden und sieht beim Aufrufen folgendermaßen aus:

Jetzt können wir die Zielmethode auswählen, um fortzufahren. Beachten Sie außerdem, dass IntelliJ die äußerste Methode immer ganz oben auf die Liste setzt. Das bedeutet, dass wir durch Drücken von Umschalt + F7 | schnell darauf zugreifen können Geben Sie ein .

3. Rahmen fallen lassen

Möglicherweise stellen wir fest, dass bereits eine Verarbeitung stattgefunden hat, an der wir interessiert sind (z. B. Berechnung des aktuellen Methodenarguments). In diesem Fall ist es möglich, die aktuellen JVM-Stapelrahmen zu löschen, um sie erneut zu verarbeiten.

Betrachten Sie die folgende Situation:

Angenommen, wir möchten die getArg1- Verarbeitung debuggen, also löschen wir den aktuellen Frame ( doJob- Methode):

Jetzt sind wir in der vorherigen Methode :

Die Aufrufargumente sind jedoch bereits zu diesem Zeitpunkt berechnet. Daher müssen wir auch den aktuellen Frame löschen :

Jetzt können wir die Verarbeitung erneut ausführen, indem wir Step Into aufrufen .

4. Feld-Haltepunkte

Manchmal werden nicht private Felder von anderen Klassen geändert, nicht über Setter, sondern direkt (dies ist bei Bibliotheken von Drittanbietern der Fall, bei denen wir den Quellcode nicht steuern).

In solchen Situationen ist es möglicherweise schwer zu verstehen, wann die Änderung durchgeführt wird. Mit IntelliJ können Haltepunkte auf Feldebene erstellt werden, um dies zu verfolgen.

Sie werden wie gewohnt eingestellt - klicken Sie mit der linken Maustaste auf die linke Editorrinne in der Feldlinie. Danach ist es möglich, Haltepunkteigenschaften zu öffnen (Rechtsklick auf die Haltepunktmarke) und zu konfigurieren, ob wir an den Lese-, Schreib- oder beidem des Feldes interessiert sind :

5. Protokollieren von Haltepunkten

Manchmal wissen wir, dass die Anwendung eine Rennbedingung enthält, wissen aber nicht genau, wo sie sich befindet. Es kann eine Herausforderung sein, es festzunageln, insbesondere wenn Sie mit neuem Code arbeiten.

Wir können den Quellen unseres Programms Debugging-Anweisungen hinzufügen. Es gibt jedoch keine solche Möglichkeit für Bibliotheken von Drittanbietern.

Die IDE kann hier helfen - sie ermöglicht das Setzen von Haltepunkten, die die Ausführung nach einem Treffer nicht blockieren, sondern stattdessen Protokollierungsanweisungen erstellen .

Betrachten Sie das folgende Beispiel:

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; }

Angenommen, wir möchten die Parameter des tatsächlichen isInterested- Aufrufs protokollieren .

Erstellen wir einen nicht blockierenden Haltepunkt in der Zielmethode ( Umschalt + Linksklick auf die linke Editor-Rinne). Öffnen Sie anschließend die Eigenschaften (klicken Sie mit der rechten Maustaste auf den Haltepunkt) und definieren Sie den zu protokollierenden Zielausdruck :

Wenn Sie die Anwendung ausführen (beachten Sie, dass der Debug-Modus weiterhin verwendet werden muss), wird die Ausgabe angezeigt:

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

6. Bedingte Haltepunkte

Es kann vorkommen, dass eine bestimmte Methode von mehreren Threads gleichzeitig aufgerufen wird und wir die Verarbeitung nur für ein bestimmtes Argument debuggen müssen.

Mit IntelliJ können Haltepunkte erstellt werden, die die Ausführung nur unterbrechen, wenn eine benutzerdefinierte Bedingung erfüllt ist .

Hier ist ein Beispiel, das den obigen Quellcode verwendet:

Jetzt stoppt der Debugger nur dann am Haltepunkt, wenn das angegebene Argument größer als 3 ist.

7. Objektmarkierungen

Dies ist die leistungsstärkste und am wenigsten bekannte IntelliJ-Funktion. Im Wesentlichen ist es ganz einfach: Wir können JVM-Objekten benutzerdefinierte Beschriftungen hinzufügen .

Schauen wir uns eine Anwendung an, mit der wir sie demonstrieren:

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. Markierungen erstellen

Ein Objekt kann markiert werden, wenn eine Anwendung an einem Haltepunkt gestoppt wird und das Ziel über Stapelrahmen erreichbar ist.

Wählen Sie es aus, drücken Sie F11 ( Aktion Objekt markieren) und definieren Sie den Zielnamen:

7.2. Markierungen anzeigen

Jetzt können wir unsere benutzerdefinierten Objektbezeichnungen auch in anderen Teilen der Anwendung sehen:

Das Coole ist, dass selbst wenn ein markiertes Objekt momentan nicht über Stapelrahmen erreichbar ist, wir seinen Status sehen können - öffnen Sie ein Dialogfeld " Ausdruck auswerten" oder fügen Sie eine neue Uhr hinzu und geben Sie den Namen der Marke ein.

IntelliJ bietet an, es mit dem Suffix _DebugLabel zu vervollständigen :

Wenn wir es auswerten, wird der Status des Zielobjekts angezeigt:

7.3. Markierungen als Bedingungen

Es ist auch möglich, Markierungen unter Haltepunktbedingungen zu verwenden:

8. Fazit

Wir haben eine Reihe von Techniken überprüft, die die Produktivität beim Debuggen einer Multithread-Anwendung erheblich steigern.

Dies ist normalerweise eine herausfordernde Aufgabe, und wir können die Bedeutung der Werkzeughilfe hier nicht unterschätzen.