Προγραμματισμός

Εντοπισμός σφαλμάτων με jdb

Ε: Πώς χρησιμοποιείτε αποτελεσματικά το jdb (περιλαμβάνεται στο πακέτο JDK 1.2) για τον εντοπισμό σφαλμάτων προγραμμάτων Java;

Έχω δοκιμάσει πολλές φορές, αλλά είμαι επιτυχής μόνο στη φόρτωση ενός αρχείου τάξης jdb; Δεν μπορώ να το εντοπίσω. ο βοήθεια η εντολή δεν είναι πολύ χρήσιμη.

ΕΝΑ: Κάνετε μια ενδιαφέρουσα ερώτηση. Για να είμαι ειλικρινής, έχω ποτέ μεταχειρισμένος jdb. Πάντα χρησιμοποιούσα το πρόγραμμα εντοπισμού σφαλμάτων που παρέχεται από το περιβάλλον IDE. Για να απαντήσω λοιπόν στην ερώτησή σας, έπρεπε να κάνω μια δική μου έρευνα.

Αποδεικνύεται ότι η Sun θεωρεί jdb μια απόδειξη της ιδέας για το Java Debugger API. Το Java Debugger API μας επιτρέπει να ρίξουμε μια ματιά στον χρόνο εκτέλεσης και να διορθώσουμε τον κώδικα. ο jdb είναι μόνο μία εφαρμογή ενός προγράμματος εντοπισμού σφαλμάτων που χρησιμοποιεί το API. Σε σύγκριση με τους οπτικούς εντοπιστές εντοπισμού σφαλμάτων με τους οποίους είμαι εξοικειωμένος (ναι, υποθέτω ότι είμαι wimp), δεν είναι ο ευκολότερος εντοπιστής εντοπισμού σφαλμάτων που χρησιμοποιείται - αν και είναι παρόμοιος με άλλους εντοπιστές εντολών εντολών, gdb.

Εν πάση περιπτώσει, στην ερώτησή σας. Πριν επιχειρήσετε να διορθώσετε τον κωδικό σας, βεβαιωθείτε ότι χρησιμοποιείτε το -σολ επιλογή κατά τη σύνταξη των μαθημάτων σας. Αυτή η επιλογή λέει στον μεταγλωττιστή να περιλαμβάνει πληροφορίες εντοπισμού σφαλμάτων στο αρχείο τάξης.

Ας ορίσουμε μια επινοημένη τάξη για δοκιμή:

δημόσια τάξη TestMe {private int int_value; ιδιωτική συμβολοσειρά string_value; public static void main (String [] args) {TestMe testMe = νέο TestMe (); testMe.setInt_value (1); testMe.setString_value ("δοκιμή"); int integer = testMe.getInt_value (); String string = testMe.getString_value (); String toString = testMe.toString (); } δημόσιο TestMe () {} δημόσιο int getInt_value () {return int_value; } δημόσια συμβολοσειρά getString_value () {return string_value; } public void setInt_value (τιμή int) {int_value = τιμή; } public void setString_value (Τιμή συμβολοσειράς) {string_value = value; } δημόσια συμβολοσειρά toString () {return "Τιμή συμβολοσειράς:" + string_value + "int value:" + int_value; }} 

Ξεκινήστε το πρόγραμμα εντοπισμού σφαλμάτων:

> jdb TestMe 

Πρέπει να δεις:

> Αρχικοποίηση jdb ...> 0xaa: class 

Ας ρίξουμε μια ματιά σε μερικές βασικές εντολές. Για να ορίσουμε σημεία διακοπής, πρέπει να γνωρίζουμε τους αριθμούς γραμμής ή τα ονόματα μεθόδων των θέσεων όπου θα θέλαμε να σπάσουμε. Για να αποκτήσετε μια λίστα μεθόδων, απλώς χρησιμοποιήστε το μεθόδους εντολή:

> μέθοδοι 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 ( ) 

Η ρύθμιση ενός σημείου διακοπής είναι απλή. Χρησιμοποιήστε την ακόλουθη σύνταξη:

σταματήστε μέσα. [] 

Ή:

σταματήστε στις: 

Πρέπει να ξεκινήσουμε τον εντοπισμό σφαλμάτων στην αρχή της κύριας μεθόδου:

> σταματήστε στο TestMe.main Breakpoint σε javaworld.TestMe.main 

Τώρα που έχουμε ένα σημείο διακοπής, μπορούμε να ξεκινήσουμε την εκτέλεση. Για να τρέξετε μέχρι το σημείο διακοπής, απλώς χρησιμοποιήστε το τρέξιμο εντολή:

> run run javaworld.TestMe running ... main [1] Breakpoint hit: 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 = νέο TestMe (); 11 testMe.setInt_value (1); 12 testMe.setString_value ("δοκιμή"); 13 14 int integer = testMe.getInt_value (); κύρια [1] 

Στη συνέχεια, θα θέλαμε βήμα μέσα από μερικές γραμμές κώδικα και δείτε τι άλλαξε:

main [1] step main [1] Breakpoint hit: javaworld.TestMe. (TestMe: 20) main [1] locals Ορίσματα μεθόδου: Τοπικές μεταβλητές: this = Τιμή συμβολοσειράς: τιμή null int: 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] Breakpoint hit: java.lang.Object. (Object: 27) main [1] list Δεν είναι δυνατή η εύρεση του Object.java main [1] step main [1] Breakpoint hit: javaworld.TestMe. (TestMe: 22) main [1] list 18} 19 20 public TestMe () 21 {22 =>} 23 24 public int getInt_value () 25 {26 return int_value; main [1] step main [1] Breakpoint hit: 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 = νέο TestMe (); 11 testMe.setInt_value (1); 12 testMe.setString_value ("δοκιμή"); 13 14 int integer = testMe.getInt_value (); main [1] step main [1] Breakpoint hit: javaworld.TestMe.main (TestMe: 11) main [1] list 7 8 public static void main (String [] args) 9 {10 TestMe testMe = νέο TestMe (); 11 => testMe.setInt_value (1); 12 testMe.setString_value ("δοκιμή"); 13 14 int integer = testMe.getInt_value (); 15 string string = testMe.getString_value (); main [1] locals Ορίσματα μεθόδου: Τοπικές μεταβλητές: args = testMe = Τιμή συμβολοσειράς: null int τιμή: 0 

Μετά το καθένα βήμα, Κάλεσα το λίστα εντολή για να δω πού ήμουν στον κώδικα. Η τιμή επιστροφής από την εντολή αναφέρει τον αριθμό γραμμής, αλλά κατά κάποιον τρόπο αυτό δεν με βοήθησε πολύ.

Οπως εμείς βήμα, βλέπουμε ότι η κύρια μέθοδος είναι η κατασκευή ενός Δοκιμασε με παράδειγμα. Κάθε βήμα μας οδηγεί στον κατασκευαστή και τέλος επιστρέφουμε στην κύρια μέθοδο. ο ντόπιοι Η εντολή παραθέτει όλες τις τοπικές μεταβλητές που είναι ορατές στην τρέχουσα στοίβα. Βλέπουμε ότι σε αυτό το σημείο της κύριας μεθόδου υπάρχουν μόνο δύο τοπικές μεταβλητές: υποστηρίζει και δοκιμασε με.

Με τη χρήση βήμα, μπορούμε να εισέλθουμε σε οποιαδήποτε από τις μεθόδους για να δούμε τι συμβαίνει. Όταν συνδυάζουμε βήμα με την ντόπιοι εντολή μπορούμε να δούμε τις μεταβλητές μας:

main [1] step main [1] Breakpoint hit: javaworld.TestMe.setInt_value (TestMe: 36) main [1] list 32} 33 34 public void setInt_value (int value) 35 {36 => int_value = τιμή; 37} 38 39 public void setString_value (String value) 40 {main [1] locals Ορίσματα μεθόδου: Τοπικές μεταβλητές: τιμή = 1 αυτό = Τιμή συμβολοσειράς: null int τιμή: 0 

Αν εμείς βήμα για άλλη μια φορά, καταλήγουμε στο setInt_value () μέθοδος. Αν εμείς βήμα δύο ακόμη φορές, η μέθοδος θα ορίσει το int_value μέλος στο 1 και επιστροφή. (Για να βεβαιωθείτε ότι η μέθοδος ορίζει την τιμή, χρησιμοποιήστε το ντόπιοι εντολή.)

Φυσικά, όταν εμείς βήμα, δεν θα θέλουμε πάντα να εντοπίζουμε κάθε μέθοδο που αντιμετωπίζουμε. Ορισμένες κλήσεις μεθόδου μπορούν να φωλιάσουν πολύ βαθιά. Εάν αναγκάσαμε να εντοπίσουμε μια ολόκληρη ιεραρχία, ίσως να μην τελειώσουμε ποτέ. Ευτυχώς, jdb έχει έναν τρόπο εκτέλεσης μιας μεθόδου χωρίς ανίχνευση σε αυτήν τη μέθοδο: το Επόμενο εντολή.

jdb παρέχει επίσης μερικά άλλα βήμα εντολές. ο Στέπη Η εντολή εκτελεί την τρέχουσα εντολή. Με άλλα λόγια, ο κωδικός στο => θα εκτελεστεί, αλλά η τρέχουσα γραμμή δεν θα προχωρήσει στην επόμενη οδηγία. Μπορείς να καλέσεις Στέπη ένα εκατομμύριο φορές, αλλά το => εμφανίζεται από το λίστα η εντολή δεν θα κινηθεί.

jdb παρέχει επίσης το ανεβάζω εντολή. ο ανεβάζω η κλήση εκτελείται έως ότου η τρέχουσα μέθοδος επιστρέψει στον καλούντα. Με απλά λόγια, αυτό το stepper εκτελεί μια μέθοδο και τίποτα άλλο. Πάρτε το ακόλουθο τμήμα κώδικα ως παράδειγμα:

int integer = testMe.getInt_value (); 

Εάν αυτή είναι η τρέχουσα γραμμή μας και τρέχουμε ανεβάζω, ο getInt_value () η μέθοδος θα εκτελεστεί. Ωστόσο, αυτό είναι όλο που θα συμβεί. Η τιμή επιστροφής δεν θα οριστεί σε ακέραιος αριθμός.

jdb μας επιτρέπει επίσης να ορίσουμε πολλά σημεία διακοπής. Για να μεταβείτε από το ένα σημείο διακοπής απευθείας στο άλλο, jdb παρέχει το συνέχεια εντολή.

Τέλος, υπάρχουν στιγμές που θέλουμε να δούμε όλα τα μέλη μιας παρουσίας ή μιας τάξης. Ευτυχώς, jdb παρέχει το εγκαταλείπω και Τυπώνω εντολές:

main [1] dump TestMe TestMe = 0xa9: class (javaworld.TestMe) {superclass = 0x2: class (java.lang.Object) loader = (sun.misc.Launcher $ AppClassLoader) 0xaa} main [1] εκτύπωση 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 = Τιμή συμβολοσειράς: test τιμή int: 1 

Όταν τρέχετε εγκαταλείπω ή Τυπώνω σε μια τάξη, λαμβάνετε πληροφορίες τάξης, οι οποίες περιλαμβάνουν πληροφορίες για superclass και φορτωτές. Όταν τρέχετε εγκαταλείπω και Τυπώνω σε μια παρουσία, λαμβάνετε πληροφορίες παρουσίας, όπως μέλη δεδομένων και τις τρέχουσες τιμές τους.

jdb παρέχει επίσης εντολές για να κατεβείτε και να λερώσετε τα νήματα και τις στοίβες. Ωστόσο, αυτές οι εντολές είναι πραγματικά πέρα ​​από το πεδίο εφαρμογής του a jdb εισαγωγή

Ένα τελευταίο σημείο: μπορείτε να ρωτήσετε, "Πώς χρησιμοποιείτε αποτελεσματικά jdbΗ αποτελεσματικότητα της χρήσης θα εξαρτηθεί από το επίπεδο άνεσής σας με jdb. Όταν χρησιμοποιείτε για πρώτη φορά jdb, η πιο σημαντική εντολή είναι βοήθεια. ο βοήθεια Η εντολή παραθέτει κάθε εντολή και παρέχει μερικές βασικές πληροφορίες για να σας βοηθήσει να ξεκινήσετε. Μόλις έχετε το βοήθεια mastered master, θα βρείτε τον εαυτό σας χρησιμοποιώντας τις εντολές που ορίζουν σημεία διακοπής, μαζί με βήμα και λίστα. Οποιοσδήποτε συνδυασμός αυτών των εντολών θα σας επιτρέψει να ξεκινήσετε τη χρήση jdb. βήμα, λίστα, βήμα, λίστα... θα σας βοηθήσει να εντοπίσετε γρήγορα κώδικα που σας βομβαρδίζει.

Μάθετε περισσότερα σχετικά με αυτό το θέμα

  • "Java Language Debugging", από τον ιστότοπο Postech ME

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

  • "jdbΤο Java Debugger, "από Αναφορά προγραμματιστή Java, Mike Cohen, et αϊ. (Sams.net Publishing, 1996)

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

Αυτή η ιστορία, "Debug with jdb" δημοσιεύθηκε αρχικά από το JavaWorld.