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 help
Befehl 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 jdb
einen 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 jdb
ist 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 -g
Option 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 methods
Befehl:
> 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 run
Befehl , 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 list
Befehl 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 step
ein 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 step
rief ich den list
Befehl 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 step
sehen, besteht die Hauptmethode darin, eine TestMe
Instanz zu erstellen. Jeder Schritt führt uns durch den Konstruktor und schließlich zurück zur Hauptmethode. Der locals
Befehl 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: args
und testMe
.
Mit step
können wir in jede der Methoden eindringen, um zu sehen, was los ist. Wenn wir step
mit dem locals
Befehl 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 step
noch einmal, landen wir in der setInt_value()
Methode. Wenn wir es step
noch zweimal tun , setzt die Methode das int_value
Mitglied auf 1
und kehrt zurück. (Um zu überprüfen, ob die Methode den Wert festgelegt hat, verwenden Sie den locals
Befehl.)
Wenn wir step
wollen, 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 jdb
gibt es eine Möglichkeit, eine Methode auszuführen, ohne auf diese Methode zurückzugreifen: den next
Befehl.
jdb
bietet auch einige andere step
Befehle. Der stepi
Befehl 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 stepi
millionenfach anrufen , aber der =>
vom list
Befehl angezeigte Befehl wird nicht verschoben.
jdb
bietet auch den step up
Befehl. Der step up
Aufruf 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
.
jdb
Außerdem können wir mehrere Haltepunkte festlegen. Um von einem Haltepunkt direkt zum nächsten zu gelangen, jdb
wird der cont
Befehl bereitgestellt.
Schließlich gibt es Zeiten, in denen wir alle Mitglieder einer Instanz oder Klasse betrachten möchten. Zum Glück jdb
bietet die dump
und print
Befehle:
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 dump
oder print
bearbeiten, erhalten Sie Klasseninformationen, einschließlich Informationen zu Oberklassen und Ladern. Wenn Sie laufen dump
und print
auf einer Instanz erhalten Sie beispielsweise Informationen, wie Datenelemente und ihre aktuellen Werte.
jdb
bietet auch Befehle zum Herunterfahren und Verschmutzen der Threads und Stapel. Diese Befehle gehen jedoch wirklich über den Rahmen eines jdb
Intro 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 jdb
ist der wichtigste Befehl help
. Der help
Befehl listet jeden Befehl auf und enthält einige grundlegende Informationen, die Ihnen den Einstieg erleichtern. Sobald Sie den help
Befehl beherrschen, werden Sie die Befehle verwenden, mit denen Haltepunkte zusammen mit step
und festgelegt werden list
. Mit jeder Kombination dieser Befehle können Sie loslegen jdb
. step
, list
, step
, list
Sollte ... 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/
- "
jdb
The 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.