Отстраняване на грешки с jdb

В: Как ефективно използвате jdb (включен в пакета JDK 1.2) за отстраняване на грешки в Java програми?

Опитвал съм много пъти, но имам успех само в зареждането на файл от клас в jdb; Не мога да го отстраня. В helpзаповедта не е от голяма полза.

О: Задавате интересен въпрос. За да бъда честен, никога не съм използвал jdb. Винаги съм използвал дебъгера, предоставен от моята среда на IDE. Така че, за да отговоря на въпроса ви, трябваше да направя малко собствено проучване.

Оказва се, че Sun счита jdbдоказателство за концепция за API за отстраняване на грешки в Java. API за отстраняване на грешки Java ни позволява да надникнем в изпълнението и да отстраним грешки в нашия код. Това jdbе само една реализация на дебъгер, който използва API. В сравнение с визуалните дебъгъри, с които съм запознат (да, предполагам, че съм wimp), това не е най-лесният дебъгер за използване - въпреки че е подобен на други дебъгъри на командния ред, като например gdb.

Във всеки случай, на вашия въпрос. Преди да се опитате да отстраните грешките на вашия код, не забравяйте да използвате -gопцията, докато компилирате класовете си. Тази опция казва на компилатора да включва информация за отстраняване на грешки във вашия файл на класа.

Нека дефинираме измислен клас за тестване:

публичен клас TestMe {private int int_value; частен низ string_value; публична статична празнота main (String [] args) {TestMe testMe = new TestMe (); testMe.setInt_value (1); testMe.setString_value ("тест"); int цяло число = testMe.getInt_value (); Низ низ = testMe.getString_value (); String toString = testMe.toString (); } public TestMe () {} public int getInt_value () {return int_value; } публичен низ getString_value () {връщане 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; }}

Стартирайте дебъгера:

> jdb TestMe 

Трябва да видиш:

> Инициализиране на jdb ...> 0xaa: клас 

Нека да разгледаме някои основни команди. За да зададем точки на прекъсване, трябва да знаем номерата на редовете или имената на методите на местата, където бихме искали да прекъснем. За да получите списък с методи, просто използвайте methodsкомандата:

> методи 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 Точка на прекъсване, зададена в javaworld.TestMe.main 

Сега, когато имаме точка на прекъсване, можем да започнем изпълнението. За да стигнете до точката на прекъсване, просто използвайте runкомандата:

> run run javaworld.TestMe running ... main [1] Попадане в точка на прекъсване: javaworld.TestMe.main (TestMe: 10) 

В този момент дебъгерът спира изпълнението на първия ред на основния метод. Забележете, че курсорът се е променил, за да отразява метода, в който се намираме в момента.

В listкоманда ще покаже кода в точката на прекъсване. Стрелка показва мястото, където дебъгерът е спрял изпълнението.

главен [1] списък 6 частен низ string_value; 7 8 публични статични void main (String [] args) 9 {10 => TestMe testMe = new TestMe (); 11 testMe.setInt_value (1); 12 testMe.setString_value ("тест"); 13 14 int integer = testMe.getInt_value (); главен [1]

След това ще искаме да stepпрегледаме няколко реда код и да видим какво се е променило:

main [1] step main [1] Попадане в точка на прекъсване: javaworld.TestMe. (TestMe: 20) main [1] local Аргументи на метода: Локални променливи: this = String value: null int value: 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] Удар на точката на прекъсване: java.lang.Object. (Object: 27) main [1] list Не може да се намери Object.java main [1] step main [1] Удар на точката на прекъсване: 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] стъпка main [1] Попадане в точка на прекъсване: javaworld.TestMe.main (TestMe: 10) main [1] list 6 private String string_value; 7 8 публични статични void main (String [] args) 9 {10 => TestMe testMe = new TestMe (); 11 testMe.setInt_value (1); 12 testMe.setString_value ("тест");13 14 int integer = testMe.getInt_value (); главна [1] стъпка главна [1] Попадане в точка на прекъсване: javaworld.TestMe.main (TestMe: 11) main [1] списък 7 8 публична статична празнота main (String [] args) 9 {10 TestMe testMe = new TestMe (); 11 => testMe.setInt_value (1); 12 testMe.setString_value ("тест"); 13 14 int integer = testMe.getInt_value (); 15 низ низ = testMe.getString_value (); main [1] local Аргументи на метода: Локални променливи: args = testMe = String стойност: null int стойност: 0main [1] local Аргументи на метода: Локални променливи: args = testMe = String стойност: null int стойност: 0main [1] local Аргументи на метода: Локални променливи: args = testMe = String стойност: null int стойност: 0

След всеки stepизвиках listкомандата, за да видя къде съм в кода. Връщаната стойност от командата изброява номера на реда, но по някакъв начин това наистина не ми помогна особено.

Както ние stepвиждаме, че основният метод е конструирането на TestMeекземпляр. Всяка стъпка ни превежда през конструктора и накрая отново към основния метод. В localsсписъците команда всички на локалните променливи видими в текущия стека. Виждаме, че в този момент в основния метод има само две локални променливи: argsи testMe.

Като използваме step, можем да влезем във всеки от методите, за да видим какво се случва. Когато комбинираме stepс localsкомандата, можем да видим нашите променливи:

main [1] step main [1] Попадане в точка на прекъсване: 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 Аргументи на метода: Локални променливи: value = 1 this = String value: null int value: 0

Ако stepоще веднъж стигнем до setInt_value()метода. Ако имаме stepоще два пъти, методът ще зададе на int_valueчлена 1и да се върне. (За да проверите дали методът е задал стойността, използвайте localsкомандата.)

Разбира се, когато ние stepне винаги ще искаме да проследим всеки метод, който срещаме. Някои извиквания на методи могат да се вложат много дълбоко. Ако бяхме принудени да проследим цяла йерархия, може би никога няма да завършим. За щастие jdbима начин да изпълни метод без проследяване в този метод: nextкомандата.

jdbпредоставя и няколко други stepкоманди. В stepiзаповедта се изпълнява текущата инструкция. С други думи, кодът на =>волята ще се изпълни, но текущият ред няма да премине към следващата инструкция. Можете да се обадите stepiмилион пъти, но =>показаното от listкомандата няма да се премести.

jdbсъщо предоставя step upкомандата. В step upпоканата се изпълнява, докато сегашният метод се връща в повикващия. Просто казано, този степер изпълнява метод и нищо друго. Вземете за пример следния сегмент на кода:

int цяло число = testMe.getInt_value (); 

Ако това е нашата текуща линия и ние изпълним step up, getInt_value()методът ще се изпълни. Това обаче е всичко, което ще се случи. Връщаната стойност няма да бъде зададена на integer.

jdbсъщо ни позволява да зададем множество точки на прекъсване. За да преминете от една точка на прекъсване директно към следващата, jdbпредоставя contкомандата.

И накрая, има моменти, когато искаме да разгледаме всички членове на екземпляр или клас. За щастие, jdbосигурява dumpи printкоманди:

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: 1 

Когато стартирате dumpили printв клас, получавате информация за класа, която включва информация за суперклас и товарач. Когато стартирате dumpи printна даден екземпляр, получавате информация за инстанция, като членове на данни и техните текущи стойности.

jdbсъщо така предоставя команди за сваляне и замърсяване в нишките и стековете. Тези команди обаче наистина са извън обхвата на едно jdbвъведение.

Една последна точка: можете да попитате: "Как ефективно използвате jdb?" Ефективността на използването ще зависи от нивото на комфорт с jdb. Когато използвате за първи път jdb, най-важната команда е help. В helpсписъците командни всяка команда и осигурява основна информация ще ви помогнат да започнете. След като сте helpусвоили командата, ще откриете, че използвате командите, които задават точки на прекъсване, заедно с stepи list. Всяка комбинация от тези команди ще ви позволи да започнете да използвате jdb. step, list, step, list... трябва да ви помогне бързо да намерите код, който е бомбардирането на вас.

Научете повече за тази тема

  • „Отстраняване на грешки в Java Java“ от уебсайта на Postech ME

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

  • " jdbJava Debugger", от Справочник за разработчици на Java, Mike Cohen, et al. (Издателство Sams.net, 1996)

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

Тази история „Отстраняване на грешки с jdb“ е публикувана първоначално от JavaWorld.