Debuggen mit jdb

F: Wie können Sie jdb (im JDK 1.2-Paket enthalten) effektiv zum Debuggen von Java-Programmen verwenden?

Ich habe es viele Male versucht, aber es gelingt mir nur, eine Klassendatei in zu laden jdb. Ich kann es nicht debuggen. Der helpBefehl ist nicht sehr nützlich.

A: Sie stellen eine interessante Frage. Um ehrlich zu sein, habe ich noch nie benutzt jdb. Ich habe immer den von meiner IDE-Umgebung bereitgestellten Debugger verwendet. Um Ihre Frage zu beantworten, musste ich selbst ein wenig recherchieren.

Es stellt sich heraus, dass Sun jdbeinen Proof of Concept für die Java Debugger-API in Betracht zieht. Mit der Java Debugger API können wir einen Blick in die Laufzeit werfen und unseren Code debuggen. Dies jdbist nur eine Implementierung eines Debuggers, der die API verwendet. Im Vergleich zu den mir bekannten visuellen Debuggern (ja, ich glaube, ich bin ein Weichei) ist es nicht der am einfachsten zu verwendende Debugger - obwohl er anderen Befehlszeilen-Debuggern ähnlich ist, wie z gdb.

Wie auch immer, weiter zu deiner Frage. Stellen Sie vor dem Versuch, Ihren Code zu debuggen, sicher, dass Sie die -gOption beim Kompilieren Ihrer Klassen verwenden. Diese Option weist den Compiler an, Debugging-Informationen in Ihre Klassendatei aufzunehmen.

Definieren wir eine erfundene Klasse zum Testen:

öffentliche Klasse TestMe {private int int_value; private String string_value; public static void main (String [] args) {TestMe testMe = new TestMe (); testMe.setInt_value (1); testMe.setString_value ("test"); int integer = testMe.getInt_value (); String string = testMe.getString_value (); String toString = testMe.toString (); } public TestMe () {} public int getInt_value () {return int_value; } public String getString_value () {return string_value; } public void setInt_value (int value) {int_value = value; } public void setString_value (String value) {string_value = value; } public String toString () {return "String value:" + string_value + "int value:" + int_value; }}

Starten Sie den Debugger:

> jdb TestMe 

Das solltest du sehen:

> JDB initialisieren ...> 0xaa: Klasse 

Schauen wir uns einige grundlegende Befehle an. Um Haltepunkte zu setzen, müssen wir die Zeilennummern oder Methodennamen der Stellen kennen, an denen wir brechen möchten. Um eine Liste der Methoden zu erhalten, verwenden Sie einfach den folgenden methodsBefehl:

> Methoden TestMe void main (java.lang.String []) void () int getInt_value () java.lang.String getString_value () void setInt_value (int) void setString_value (java.lang.String) java.lang.String toString ( ) 

Das Festlegen eines Haltepunkts ist einfach. Verwenden Sie die folgende Syntax:

Halt an. [] 

Oder:

halte bei : 

Wir sollten am Anfang der Hauptmethode mit dem Debuggen beginnen:

> Stopp in TestMe.main Haltepunkt in javaworld.TestMe.main gesetzt 

Nachdem wir einen Haltepunkt haben, können wir mit der Ausführung beginnen. Verwenden Sie einfach den folgenden runBefehl , um zum Haltepunkt zu gelangen :

> run run javaworld.TestMe running ... main [1] Haltepunkt getroffen: javaworld.TestMe.main (TestMe: 10) 

Zu diesem Zeitpunkt stoppt der Debugger die Ausführung in der ersten Zeile der Hauptmethode. Beachten Sie, dass sich der Cursor geändert hat, um die Methode widerzuspiegeln, in der wir uns gerade befinden.

Der listBefehl zeigt den Code am Haltepunkt an. Ein Pfeil zeigt die Stelle an, an der der Debugger die Ausführung angehalten hat.

main [1] list 6 private String string_value; 7 8 public static void main (String [] args) 9 {10 => TestMe testMe = new TestMe (); 11 testMe.setInt_value (1); 12 testMe.setString_value ("test"); 13 14 int integer = testMe.getInt_value (); main [1]

Als nächstes wollen wir stepein paar Codezeilen durchgehen und sehen, was sich geändert hat:

main [1] step main [1] Haltepunkt getroffen: javaworld.TestMe. (TestMe: 20) main [1] local Methodenargumente: Lokale Variablen: this = String-Wert: null int-Wert: 0 main [1] list 16 17 String toString = testMe.toString (); 18} 19 20 => public TestMe () 21 {22} 23 24 public int getInt_value () main [1] step main [1] Haltepunkt-Treffer: java.lang.Object. (Objekt: 27) Hauptliste [1] Objekt.java Haupt [1] Schritt Haupt [1] Haltepunkttreffer: javaworld.TestMe konnte nicht gefunden werden. (TestMe: 22) Hauptliste [1] 18} 19 20 public TestMe () 21 {22 =>} 23 24 public int getInt_value () 25 {26 return int_value; main [1] step main [1] Haltepunkt getroffen: javaworld.TestMe.main (TestMe: 10) main [1] list 6 private String string_value; 7 8 public static void main (String [] args) 9 {10 => TestMe testMe = new TestMe (); 11 testMe.setInt_value (1); 12 testMe.setString_value ("test");13 14 int integer = testMe.getInt_value (); main [1] step main [1] Haltepunkt getroffen: javaworld.TestMe.main (TestMe: 11) main [1] list 7 8 public static void main (String [] args) 9 {10 TestMe testMe = new TestMe (); 11 => testMe.setInt_value (1); 12 testMe.setString_value ("test"); 13 14 int integer = testMe.getInt_value (); 15 String string = testMe.getString_value (); main [1] local Methodenargumente: Lokale Variablen: args = testMe = String-Wert: null int-Wert: 0main [1] local Methodenargumente: Lokale Variablen: args = testMe = String-Wert: null int-Wert: 0main [1] local Methodenargumente: Lokale Variablen: args = testMe = String-Wert: null int-Wert: 0

Nach jedem steprief ich den listBefehl auf, um zu sehen, wo ich mich im Code befand. Der Rückgabewert des Befehls listete die Zeilennummer auf, aber irgendwie hat mir das nicht wirklich geholfen.

Wie wir stepsehen, besteht die Hauptmethode darin, eine TestMeInstanz zu erstellen. Jeder Schritt führt uns durch den Konstruktor und schließlich zurück zur Hauptmethode. Der localsBefehl listet alle lokalen Variablen auf, die im aktuellen Stapel sichtbar sind. Wir sehen, dass es an dieser Stelle in der Hauptmethode nur zwei lokale Variablen gibt: argsund testMe.

Mit stepkönnen wir in jede der Methoden eindringen, um zu sehen, was los ist. Wenn wir stepmit dem localsBefehl kombinieren, können wir unsere Variablen sehen:

main [1] step main [1] Haltepunkt getroffen: javaworld.TestMe.setInt_value (TestMe: 36) main [1] list 32} 33 34 public void setInt_value (int value) 35 {36 => int_value = value; 37} 38 39 public void setString_value (String value) 40 {main [1] local Methodenargumente: Lokale Variablen: value = 1 this = String value: null int value: 0

Wenn wir stepnoch einmal, landen wir in der setInt_value()Methode. Wenn wir es stepnoch zweimal tun , setzt die Methode das int_valueMitglied auf 1und kehrt zurück. (Um zu überprüfen, ob die Methode den Wert festgelegt hat, verwenden Sie den localsBefehl.)

Wenn wir stepwollen, wollen wir natürlich nicht immer jede Methode verfolgen, auf die wir stoßen. Einige Methodenaufrufe können sehr tief verschachtelt sein. Wenn wir gezwungen wären, eine ganze Hierarchie zu verfolgen, könnten wir niemals fertig werden. Glücklicherweise jdbgibt es eine Möglichkeit, eine Methode auszuführen, ohne auf diese Methode zurückzugreifen: den nextBefehl.

jdbbietet auch einige andere stepBefehle. Der stepiBefehl führt die aktuelle Anweisung aus. Mit anderen Worten, der Code am =>wird ausgeführt, aber die aktuelle Zeile wird nicht zum nächsten Befehl weitergeleitet. Sie können stepimillionenfach anrufen , aber der =>vom listBefehl angezeigte Befehl wird nicht verschoben.

jdbbietet auch den step upBefehl. Der step upAufruf wird ausgeführt, bis die aktuelle Methode zu ihrem Aufrufer zurückkehrt. Einfach ausgedrückt, dieser Stepper führt eine Methode aus und sonst nichts. Nehmen Sie als Beispiel das folgende Codesegment:

int integer = testMe.getInt_value (); 

Wenn dies unsere aktuelle Zeile ist und wir ausführen step up, wird die getInt_value()Methode ausgeführt. Das ist jedoch alles, was passieren wird. Der Rückgabewert wird nicht auf gesetzt integer.

jdbAußerdem können wir mehrere Haltepunkte festlegen. Um von einem Haltepunkt direkt zum nächsten zu gelangen, jdbwird der contBefehl bereitgestellt.

Schließlich gibt es Zeiten, in denen wir alle Mitglieder einer Instanz oder Klasse betrachten möchten. Zum Glück jdbbietet die dumpund printBefehle:

main [1] dump TestMe TestMe = 0xa9: class (javaworld.TestMe) {superclass = 0x2: class (java.lang.Object) loader = (sun.misc.Launcher $ AppClassLoader) 0xaa} main [1] print TestMe TestMe = 0xa9: class (javaworld.TestMe) main [1] dump testMe testMe = (javaworld.TestMe) 0xec {private java.lang.String string_value = test private int int_value = 1} main [1] print testMe testMe = String value: test int-Wert: 1 

Wenn Sie eine Klasse ausführen dumpoder printbearbeiten, erhalten Sie Klasseninformationen, einschließlich Informationen zu Oberklassen und Ladern. Wenn Sie laufen dumpund printauf einer Instanz erhalten Sie beispielsweise Informationen, wie Datenelemente und ihre aktuellen Werte.

jdbbietet auch Befehle zum Herunterfahren und Verschmutzen der Threads und Stapel. Diese Befehle gehen jedoch wirklich über den Rahmen eines jdbIntro hinaus.

Ein letzter Punkt: Sie können fragen: "Wie setzen Sie effektiv ein jdb?" Die Effektivität der Verwendung hängt von Ihrem Komfortniveau ab jdb. Bei der ersten Verwendung jdbist der wichtigste Befehl help. Der helpBefehl listet jeden Befehl auf und enthält einige grundlegende Informationen, die Ihnen den Einstieg erleichtern. Sobald Sie den helpBefehl beherrschen, werden Sie die Befehle verwenden, mit denen Haltepunkte zusammen mit stepund festgelegt werden list. Mit jeder Kombination dieser Befehle können Sie loslegen jdb. step, list, step, listSollte ... Ihnen helfen, schnell Code suchen , die auf Sie bombardiert werden.

Erfahren Sie mehr über dieses Thema

  • "Java Language Debugging" von der Postech ME-Website

    //mech.postech.ac.kr/Java/java.sun.com/products/JDK/debugging/

  • " jdbThe Java Debugger" aus der Java Developer's Reference von Mike Cohen et al. (Sams.net Publishing, 1996)

    //docs.online.bg/PROGRAMMING/JAVA_Developers_Reference/ch15.htm

Diese Geschichte "Debug with jdb" wurde ursprünglich von JavaWorld veröffentlicht.