Java Debugger
| Language: | Deutsch • English |
|---|
Einführung
Das Java Debugger Plugin bietet grundlegende Debug-Funktionen für Java. Damit können Groovy-Blöcke und beliebiger anderer Java-Code, der in einer entfernten JVM läuft, direkt in expecco untersucht werden.
Das Plugin erlaubt es, Haltepunkte in Java- oder Groovy-Code zu setzen. Wird ein Haltepunkt erreicht, hält das Programm an und ein Debugger erscheint. Mit ihm kann der Ausführungszustand untersucht und der Code schrittweise ausgeführt werden.
Für Groovy-Blöcke gibt es inzwischen einen in expecco eingebauten Debugger, der weder das Plugin noch dessen Lizenz benötigt: siehe Groovy-Block-Debugger.
Groovy-Block-Debugger
expecco enthält einen eingebauten Debugger für Groovy-Blöcke. Er ist Teil von expecco selbst; weder das Java Debugger Plugin noch dessen Lizenz werden benötigt. Er spricht direkt mit der JVM der Java-Bridge (über deren Debug-Port) und funktioniert mit der Groovy-Version, die die Bridge verwendet (Groovy 4 und 5). Die Abschnitte nach diesem beschreiben das Java Debugger Plugin, das für das Debuggen von reinem Java-Code weiterhin benötigt wird.
Zeilen-Haltepunkte
- Ein Haltepunkt wird durch einen Klick links neben die Zeilennummer im Groovy-Code-Editor gesetzt; ein roter Kreis markiert ihn. Ein erneuter Klick entfernt ihn. Der Debugger verbindet sich automatisch mit der Bridge.
- Wird die Zeile erreicht, öffnet sich das Debugger-Fenster. Solange es angehalten ist, ist die gesamte JVM der Bridge angehalten.
- Haltepunkte funktionieren im Code des Blocks, in Closures sowie in Klassen, Traits und Records, die im Block definiert sind.
- Ein Haltepunkt auf einer Zeile ohne ausführbaren Code (z.B. einer Leerzeile oder einem Methodenkopf) wird mit einem Warnsymbol markiert, sobald der Code des Blocks geladen ist, und eine Warnung wird ins Transcript geschrieben. Eine Zeile innerhalb einer Closure wird erst geprüft, wenn die Closure zum ersten Mal erzeugt wurde.
- "Breakpoints..." im Kontextmenü des Groovy-Code-Editors öffnet eine Liste aller Haltepunkte. Dort können Haltepunkte entfernt sowie Exception-Haltepunkte hinzugefügt oder geändert werden.
Einzelschritte
- Der Debugger bietet Fortfahren, Zeilenschritt, Hinein (in eine aufgerufene Methode oder Closure), Heraus (bis die aktuelle Methode zurückkehrt) und Abbrechen.
- Der Aufrufstack zeigt die Methoden und Closures des Blocks; Frames der Groovy-Laufzeit und des JDK werden ausgeblendet.
- Abbrechen (oder das Schließen des Debugger-Fensters) wirft im angehaltenen Thread eine java.lang.RuntimeException: aborted in the debugger; die Aktion schlägt dann mit dieser Exception fehl.
Variablen und Objekte
- Die Variablenliste zeigt die lokalen Variablen des ausgewählten Frames, einschließlich der von einer Closure eingefangenen Variablen, sowie this (im Receiver-Inspektor).
- Collections zeigen ihre Elemente ([apple, banana, cherry]), Maps ihre Einträge, Objekte von im Block definierten Klassen ihre Felder (Item(name:apple, price:1.25, qty:1)), Records z.B. als Point[x=3, y=6]. Auch Enum-Konstanten, GStrings (als Text), BigDecimal/BigInteger (als Zahlen) und die Werte der Ein- und Ausgangspins des Blocks werden angezeigt.
- Ein Doppelklick öffnet einen Inspektor auf einen Wert; geschachtelte Collections und Objekte lassen sich von dort aus öffnen. Von einer Collection werden höchstens 100 Elemente angezeigt.
- Die Werte werden gelesen, ohne Code in der JVM auszuführen (keine Aufrufe von toString()), das Ansehen von Variablen verändert also nie den Programmzustand.
Code auswerten
- Groovy-Code in der Quelltextansicht des Debuggers oder im Workspace des Variablen-Inspektors markieren und doIt, printIt oder inspectIt wählen. Der Code wird im ausgewählten Frame ausgewertet: seine lokalen Variablen, die Methoden und Felder von this und die im Block definierten Klassen können verwendet werden.
- Bei einem Halt durch einen Exception-Haltepunkt enthält die Variable exception die Exception.
- Fehler (eine vom Code geworfene Exception, ein Übersetzungsfehler) werden in einem Dialog angezeigt.
- Der Code läuft im angehaltenen Thread; die anderen Threads bleiben angehalten. Während einer Auswertung werden keine Haltepunkte ausgelöst.
Werte ändern
- Eine Variable im Variablen-Inspektor auswählen, einen Groovy-Ausdruck im Wertebereich eingeben und übernehmen (Accept): die Variable erhält den Wert des Ausdrucks. Bei primitiven Variablen (int, long, double ...) muss der Wert zum Typ passen.
- In einem Inspektor auf ein Objekt lassen sich ebenso Felder von Objekten, Elemente von Arrays und Listen und die Werte von Map-Einträgen ändern. Groovy wandelt den Wert in den Typ des Feldes um.
- Werte, die nicht geändert werden können, werden mit einer Fehlermeldung abgelehnt: unveränderliche Collections (z.B. das Ergebnis von toList() oder List.of()), die Felder von Records, Enum-Konstanten und this.
Exception-Haltepunkte
- "Break on Exception..." im Kontextmenü des Groovy-Code-Editors fragt nach einer Exception-Klasse (Vorgabe java.lang.Throwable, also jede Exception; ein im Code markierter Klassenname wird als Vorgabe übernommen) und wann angehalten werden soll: "when it is caught in the block" (wenn sie im Block gefangen wird) und/oder "when it leaves the block (not caught there)" (wenn sie den Block verlässt). Sind beide abgewählt, wird der Exception-Haltepunkt entfernt.
- Die Bridge fängt jede Exception eines Groovy-Blocks, daher bedeutet "nicht gefangen" hier: nicht vom eigenen Code des Blocks gefangen. Exceptions, die die Groovy-Laufzeit intern wirft und fängt, halten nie an.
- Beim Halt zeigt der Debugger den Frame des Block-Codes, in dem die Exception auftrat, und die Variable exception mit Klasse und Meldung der Exception.
Einschränkungen
- Es wird nur der angehaltene Thread angezeigt (keine Thread-Liste), und es gibt kein "Ausführen bis Zeile".
- Solange der Debugger angehalten ist, ist die JVM der Bridge angehalten - das betrifft auch andere Aktionen, die dieselbe Bridge verwenden.
- Collections werden angezeigt, indem die internen Felder der gängigen JDK-Collection-Klassen gelesen werden; andere Collection-Klassen erscheinen als einfache Objekte mit ihrem Typnamen.
Debugger

Der Aufbau des Java-Debugger-Fensters ähnelt den Debuggern für Smalltalk- und JavaScript-Blöcke. Es besteht aus 5 Bereichen:
1 Aufrufstack - von oben nach unten geordnet, d.h. die gerade ausgeführte Methode ist der erste Eintrag der Liste.
2 Quelltextansicht - zeigt den Quelltext der im Aufrufstack ausgewählten Methode. Der Quelltext einer Methode ist nicht immer verfügbar; Details im Abschnitt Quelltexte verwalten.
3 Inspektor für this - ein eingebetteter Inspektor auf das this-Objekt, d.h. den Empfänger der Methode.
4 Inspektor für Parameter und lokale Variablen - ein eingebetteter Inspektor, der alle im aktuellen Gültigkeitsbereich sichtbaren Methodenparameter und lokalen Variablen zeigt.
5 Thread-Liste - zeigt alle Threads der entfernten JVM. Der Aufrufstack zeigt den Stack des ausgewählten Threads.
Folgende Debug-Operationen stehen zur Verfügung:
- Continue - setzt die Ausführung fort, bis die entfernte JVM endet oder ein weiterer Haltepunkt erreicht wird.
- Abort - bricht die Ausführung des gerade laufenden expecco Groovy-Blocks ab. Führt der ausgewählte Thread keinen Groovy-Block aus, ist der Abbruch nicht erlaubt.
- Next - auch Step-over. Einzelschritt zur nächsten Zeile der ausgewählten Methode, ohne in aufgerufene Methoden hineinzugehen.
- Step - auch Step-into. Einzelschritt zur nächsten Zeile der ausgewählten Methode oder in eine aufgerufene Methode hinein.
- Out - auch Step-out. Ausführen, bis die ausgewählte Methode zurückkehrt, und beim Aufrufer anhalten.
Haltepunkte
Das Java Debugger Plugin unterstützt zwei Arten von Haltepunkten:
- Zeilen-Haltepunkte - ein klassischer Haltepunkt auf einer bestimmten Zeile in einer bestimmten Methode.
- Exception-Haltepunkte - ein Haltepunkt, der die Ausführung anhält, wenn eine Exception des angegebenen Typs geworfen wird.
Zeilen-Haltepunkte (Plugin)
Ein Zeilen-Haltepunkt kann in einen Groovy-Block oder in beliebigen anderen Java-Code gesetzt werden. Wird ein Zeilen-Haltepunkt erreicht, wird die gesamte JVM angehalten, d.h. alle laufenden Java-Threads.
Um einen Haltepunkt in einen Groovy-Block zu setzen, im Groovy-Block-Editor links neben die Zeilennummer klicken. Der Zeilen-Haltepunkt wird durch einen kleinen roten Kreis angezeigt. Ein erneuter Klick auf das Symbol entfernt ihn.
Für einen Haltepunkt in anderem Java-Code einen Java-Browser öffnen, zur gewünschten Klasse und Methode navigieren und links neben die Zeilennummer klicken.
Exception-Haltepunkte (Plugin)
Ein Exception-Haltepunkt löst aus, wenn eine Exception des angegebenen Typs (oder eines Untertyps) geworfen wird, d.h. unmittelbar bevor die Java-Anweisung throw ausgeführt wird. Das ist nützlich, wenn eine Exception geworfen, eventuell gefangen und erneut geworfen wird: so lässt sich die ursprüngliche Ursache finden und dort debuggen.
Exception-Haltepunkte lassen sich für zwei Fälle konfigurieren:
- Für gefangene Exceptions - der Haltepunkt löst aus (das Programm hält an), wenn eine Exception geworfen wird, die von einem Handler weiter unten im Aufrufstack gefangen würde. Hinweis: jeder finally- oder synchronized-Block erzeugt einen impliziten Exception-Handler für den Typ java.lang.Throwable.
- Für nicht gefangene Exceptions - der Haltepunkt löst nur aus, wenn eine Exception geworfen und von keinem Handler behandelt wird.
Warnung: Die JVM kann nicht immer zuverlässig erkennen, ob eine Exception tatsächlich gefangen wird oder nicht. Details in der JDI-Dokumentation.
Objekt-Inspektor

Noch nicht beschrieben.
Quelltexte verwalten
Das Java Debugger Plugin verwendet den Java Browser für den Zugriff auf Quelltexte. Der Quelltext einer Klasse oder Methode wird im Default-Workspace des Java Browsers gesucht. Enthält dieser keinen Quelltext für die Klasse, zeigt der Java-Debugger keinen Quelltext an. Parameter und andere lokale Variablen lassen sich trotzdem untersuchen, und Einzelschritte sind ebenfalls möglich.
Stimmen die Quelltexte nicht mit denen überein, aus denen der Java-Code übersetzt wurde, zeigt der Java-Debugger eventuell falschen Quelltext an oder die Zeilennummern passen nicht. Es gibt keine Möglichkeit zu prüfen, ob die Quelltexte zum in der entfernten JVM geladenen Code passen.
Mehr über den Default-Workspace und wie man ihm Klassen und Quelltexte hinzufügt, steht in der Dokumentation des Java Browser Plugins.
Einschränkungen (Plugin)
Die aktuelle Version des JDebugger Plugins hat einige Einschränkungen:
- Ein Zeilen-Haltepunkt kann nicht in geschachtelte Klassen gesetzt werden, d.h. nicht in innere und anonyme Klassen. Hinweis: UI-Event-Handler, etwa Button-Click-Handler, sind meist als anonyme Klassen implementiert.
- Ein Haltepunkt kann nicht in eine Klasse gesetzt werden, die in der entfernten JVM mehr als einmal geladen ist.
Diese Einschränkungen sollen in einer zukünftigen Version behoben werden.