Uvod u sučelje za otklanjanje pogrešaka Java (JDI)

1. Pregled

Možemo se zapitati kako široko priznati IDE-i poput IntelliJ IDEA i Eclipse implementiraju značajke za uklanjanje pogrešaka. Ovi se alati u velikoj mjeri oslanjaju na Java Platform Debugger Architecture (JPDA).

U ovom uvodnom članku razgovarat ćemo o API-ju Java Debug Interface API (JDI) dostupnom pod JPDA.

U isto vrijeme, napisat ćemo prilagođeni program za ispravljanje pogrešaka korak po korak, upoznavanje praktičnih JDI sučelja.

2. Uvod u JPDA

Java Platform Debugger Architecture (JPDA) skup je dobro dizajniranih sučelja i protokola koji se koriste za otklanjanje pogrešaka u Javi.

Pruža tri posebno dizajnirana sučelja za implementaciju prilagođenih programa za otklanjanje pogrešaka za razvojno okruženje u stolnim sustavima.

Za početak, sučelje Java Virtual Machine Tool (JVMTI) pomaže nam u interakciji i kontroli izvršavanja aplikacija pokrenutih u JVM-u.

Zatim, tu je Java Debug Wire Protocol (JDWP) koji definira protokol koji se koristi između aplikacije koja se testira (debuggee) i programa za ispravljanje pogrešaka.

Napokon, Java Debug Interface (JDI) koristi se za implementaciju programa za ispravljanje pogrešaka.

3. Što je JDI?

API sučelja za otklanjanje pogrešaka Java skup je sučelja koje pruža Java za provedbu frontenda programa za ispravljanje pogrešaka. JDI je najviši sloj JPDA-e.

Program za ispravljanje pogrešaka izrađen s JDI-om može ispraviti pogreške u programima koji se izvode u bilo kojem JVM-u koji podržava JPDA. Istodobno ga možemo priključiti u bilo koji sloj za uklanjanje pogrešaka.

Pruža mogućnost pristupa VM-u i njegovom stanju zajedno s pristupom varijablama programa za uklanjanje pogrešaka. Istodobno, omogućuje postavljanje prijelomnih točaka, koraka, nadzornih točaka i rukovanje nitima.

4. Postavljanje

Trebat će nam dva odvojena programa - program za otklanjanje pogrešaka i program za ispravljanje pogrešaka - da bismo razumjeli JDI-jeve implementacije.

Prvo ćemo napisati primjer programa kao program za uklanjanje pogrešaka.

Stvorimo a JDIExampleDebuggee razred s nekolicinom Niz varijable i println izjave:

javna klasa JDIExampleDebuggee {public static void main (String [] args) {String jpda = "Java Platform Debugger Architecture"; System.out.println ("Pozdrav svima, dobro došli u" + jpda); // ovdje dodajte prekid String jdi = "Java Debug Interface"; // ovdje dodamo točku prekida i također ovdje ulazimo. String text = "Danas ćemo zaroniti u" + jdi; System.out.println (tekst); }}

Zatim ćemo napisati program za ispravljanje pogrešaka.

Stvorimo a JDIExampleDebugger klasa sa svojstvima za čuvanje programa za uklanjanje pogrešaka (razred za otklanjanje pogrešaka) i brojevi linija za točke prekida (breakPointLines):

javna klasa JDIExampleDebugger {privatna klasa debugClass; privatni int [] breakPointLines; // geteri i postavljači}

4.1. LaunchingConnector

Isprva za ispravljanje pogrešaka potreban je konektor za uspostavljanje veze s ciljnim virtualnim strojem (VM).

Zatim ćemo program za uklanjanje pogrešaka postaviti kao priključak glavni argument. Napokon, konektor bi trebao pokrenuti VM za otklanjanje pogrešaka.

Da bi to učinio, JDI nudi a Bootstrap klasa koja daje primjerak LaunchingConnector. The LaunchingConnector pruža mapu zadanih argumenata, u kojoj možemo postaviti glavni argument.

Stoga, dodajmo connectAndLaunchVM metoda za JDIDebuggerExample razred:

javni VirtualMachine connectAndLaunchVM () baca iznimku {LaunchingConnector launchingConnector = Bootstrap.virtualMachineManager () .defaultConnector (); Argumenti mape = launchingConnector.defaultArguments (); arguments.get ("main"). setValue (debugClass.getName ()); povratak launchingConnector.launch (argumenti); }

Sad ćemo dodati glavni metoda za JDIDebuggerExample klase za otklanjanje pogrešaka JDIExampleDebuggee:

javna statička void glavna (String [] args) baca iznimku {JDIExampleDebugger debuggerInstance = new JDIExampleDebugger (); debuggerInstance.setDebugClass (JDIExampleDebuggee.class); int [] breakPoints = {6, 9}; debuggerInstance.setBreakPointLines (breakPoints); VirtualMachine vm = null; pokušajte {vm = debuggerInstance.connectAndLaunchVM (); vm.resume (); } catch (Iznimka e) {e.printStackTrace (); }}

Sastavimo oba predavanja, JDIExampleDebuggee (ispravljač) i JDIExampleDebugger (program za ispravljanje pogrešaka):

javac -g -cp "/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/lib/tools.jar" com / baeldung / jdi / *. java

Razgovarajmo o javac ovdje se koristi detaljno naredba.

The -g opcija generira sve informacije o otklanjanju pogrešaka bez kojih, možemo vidjeti AbsentInformationException.

I -cp će dodati alata.jar u stazi za sastavljanje klasa.

Sve JDI knjižnice dostupne su pod alata.jar JDK-a. Stoga obavezno dodajte alata.jar u stazi predavanja i prilikom sastavljanja i izvršavanja.

To je to, sada smo spremni izvršiti naš prilagođeni program za ispravljanje pogrešaka JDIExampleDebugger:

java -cp "/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/lib/tools.jar :." JDIExampleDebugger

Napomena: "." s alata.jar. Ovo će se dodati alata.jar do puta predavanja za trenutno vrijeme izvođenja (upotrijebite ";." na Windowsima).

4.2. Bootstrap i ClassPrepareRequest

Izvršavanje programa za otklanjanje pogrešaka ovdje neće dati rezultate jer nismo pripremili klasu za ispravljanje pogrešaka i postavili točke prekida.

The Virtualni stroj razred ima eventRequestManager metoda za stvaranje različitih zahtjeva poput ClassPrepareRequest, BreakpointRequest, i StepEventRequest.

Dakle, dodajmo enableClassPrepareRequest metoda za JDIExampleDebugger razred.

Ovo će filtrirati JDIExampleDebuggee klase i omogućuje ClassPrepareRequest:

javna praznina enableClassPrepareRequest (VirtualMachine vm) {ClassPrepareRequest classPrepareRequest = vm.eventRequestManager (). createClassPrepareRequest (); classPrepareRequest.addClassFilter (debugClass.getName ()); classPrepareRequest.enable (); }

4.3. ClassPrepareEvent i BreakpointRequest

Jednom, ClassPrepareRequest za JDIExampleDebuggee klasa je omogućena, red događaja VM-a počet će imati instance ClassPrepareEvent.

Koristeći ClassPrepareEvent, možemo dobiti mjesto za postavljanje točke prekida i stvara a BreakPointRequest.

Da bismo to učinili, dodajmo znak setBreakPoints metoda za JDIExampleDebugger razred:

javna praznina setBreakPoints (VirtualMachine vm, događaj ClassPrepareEvent) baca AbsentInformationException {ClassType classType = (ClassType) event.referenceType (); for (int lineNumber: breakPointLines) {Location location = classType.locationsOfLine (lineNumber) .get (0); BreakpointRequest bpReq = vm.eventRequestManager (). CreateBreakpointRequest (lokacija); bpReq.enable (); }}

4.4. BreakPointEvent i StackFrame

Do sada smo pripremili razred za ispravljanje pogrešaka i postavili točke prekida. Sada moramo uhvatiti BreakPointEvent i prikazati varijable.

JDI pruža StackFrame klase, kako bi se dobio popis svih vidljivih varijabli programa za uklanjanje pogrešaka.

Stoga, dodajmo displayVariables metoda za JDIExampleDebugger razred:

public void displayVariables (LocatableEvent event) baca IncompatibleThreadStateException, AbsentInformationException {StackFrame stackFrame = event.thread (). frame (0); if (stackFrame.location (). toString (). contains (debugClass.getName ())) {Map visibleVariables = stackFrame .getValues ​​(stackFrame.visibleVariables ()); System.out.println ("Varijable na" + stackFrame.location (). ToString () + ">"); za (Map.Entry entry: visibleVariables.entrySet ()) {System.out.println (entry.getKey (). name () + "=" + entry.getValue ()); }}}

5. Cilj za otklanjanje pogrešaka

U ovom koraku sve što trebamo je ažurirati glavni metoda JDIExampleDebugger za početak ispravljanja pogrešaka.

Stoga ćemo koristiti već raspravljene metode poput enableClassPrepareRequest, setBreakPoints, i displayVariables:

pokušajte {vm = debuggerInstance.connectAndLaunchVM (); debuggerInstance.enableClassPrepareRequest (vm); EventSet eventSet = null; while ((eventSet = vm.eventQueue (). remove ())! = null) {for (Event event: eventSet) {if (event instanceof ClassPrepareEvent) {debuggerInstance.setBreakPoints (vm, (ClassPrepareEvent) event); } if (događaj instance BreakpointEvent) {debuggerInstance.displayVariables ((BreakpointEvent) događaj); } vm.resume (); }}} catch (VMDisconnectedException e) {System.out.println ("Virtualni stroj je isključen."); } catch (Iznimka e) {e.printStackTrace (); }

Sada prvo, kompajlirajmo JDIDebuggerExample razred opet s već raspravljenim javac naredba.

I na kraju, izvršit ćemo program za ispravljanje pogrešaka zajedno sa svim promjenama da bismo vidjeli izlaz:

Varijable na com.baeldung.jdi.JDIExampleDebuggee: 6> args = instanca java.lang.String [0] (id = 93) Varijable na com.baeldung.jdi.JDIExampleDebuggee: 9> jpda = "Java Platform Debugger Architecture" args = instanca java.lang.String [0] (id = 93) Virtualni stroj je isključen.

Ura! Uspješno smo otklonili pogreške JDIExampleDebuggee razred. Istodobno smo prikazali vrijednosti varijabli na mjestima prekida (redni brojevi 6 i 9).

Stoga je naš prilagođeni program za ispravljanje pogrešaka spreman.

5.1. StepRequest

Otklanjanje pogrešaka također zahtijeva prolazak kroz kod i provjeru stanja varijabli u sljedećim koracima. Stoga ćemo stvoriti zahtjev za korakom na točki prekida.

Tijekom stvaranja instance StepRequest, moramo osigurati veličinu i dubinu koraka. Mi ćemo definirati KORAK_LINE i PRIJEĐI PREKO odnosno.

Napišimo metodu za omogućavanje zahtjeva za korakom.

Radi jednostavnosti započet ćemo koračati na zadnjoj točki prekida (redak broj 9):

javna praznina enableStepRequest (VirtualMachine vm, BreakpointEvent događaj) {// omogući zahtjev za korakom za zadnju točku prekida if (event.location (). toString (). sadrži (debugClass.getName () + ":" + breakPointLines [breakPointLines.length- 1])) {StepRequest stepRequest = vm.eventRequestManager () .createStepRequest (event.thread (), StepRequest.STEP_LINE, StepRequest.STEP_OVER); stepRequest.enable (); }}

Sada možemo ažurirati glavni metoda JDIExampleDebugger, da biste omogućili zahtjev za korakom kada je BreakPointEvent:

if (instance instance BreakpointEvent) {debuggerInstance.enableStepRequest (vm, (BreakpointEvent) događaj); }

5.2. StepEvent

Slično kao BreakPointEvent, također možemo prikazati varijable na StepEvent.

Ažurirajmo glavni metoda u skladu s tim:

if (event instanceof StepEvent) {debuggerInstance.displayVariables ((StepEvent) event); }

Napokon ćemo izvršiti program za ispravljanje pogrešaka kako bismo vidjeli stanje varijabli dok prolazimo kroz kôd:

Varijable na com.baeldung.jdi.JDIExampleDebuggee: 6> args = instanca java.lang.String [0] (id = 93) Varijable na com.baeldung.jdi.JDIExampleDebuggee: 9> args = instanca java.lang.String [0] (id = 93) jpda = "Arhitektura programa za otklanjanje pogrešaka Java platforme" na com.baeldung.jdi.JDIExampleDebuggee: 10> args = instanca java.lang.String [0] (id = 93) jpda = "Java platforma Debugger Architecture "jdi =" Java Debug Interface "Varijable na com.baeldung.jdi.JDIExampleDebuggee: 11> args = instance of java.lang.String [0] (id = 93) jpda =" Java Platform Debugger Architecture "jdi =" Sučelje za otklanjanje pogrešaka Java "text =" Danas ćemo zaroniti u varijable sučelja za otklanjanje pogrešaka Java na com.baeldung.jdi.JDIExampleDebuggee: 12> args = instanca java.lang.String [0] (id = 93) jpda = " Arhitektura programa za otklanjanje pogrešaka Java platforme "jdi =" Sučelje za otklanjanje pogrešaka Java "text =" Danas ćemo zaroniti u sučelje za otklanjanje pogrešaka Java "Virtualni stroj je isključen.

Ako usporedimo izlaz, shvatit ćemo da je program za uklanjanje pogrešaka stupio iz retka broj 9 i prikazuje varijable u svim sljedećim koracima.

6. Pročitajte izlaz za izvršenje

Mogli bismo to primijetiti println izjave JDIExampleDebuggee klasa nije bila dio izlaza za ispravljanje pogrešaka.

Prema JDI dokumentaciji, ako VM pokrenemo do LaunchingConnector, svoje izlaze i tokove pogrešaka mora pročitati Postupak objekt.

Stoga ga dodajmo na konačno klauzula naše glavni metoda:

konačno {InputStreamReader čitač = novi InputStreamReader (vm.process (). getInputStream ()); OutputStreamWriter Writer = novi OutputStreamWriter (System.out); char [] buf = novi char [512]; reader.read (buf); pisac.write (buf); Writer.flush (); }

Sada će se izvršavanjem programa za otklanjanje pogrešaka dodati i println izjave iz JDIExampleDebuggee klase na izlaz za otklanjanje pogrešaka:

Pozdrav svima, dobro došli u arhitekturu programa za otklanjanje pogrešaka Java Platforma Danas ćemo zaroniti u sučelje za otklanjanje pogrešaka Java

7. Zaključak

U ovom smo članku istražili API sučelja za otklanjanje pogrešaka Java (JDI) koji je dostupan u okviru Java Platform Debugger Architecture (JPDA).

Usput smo izradili prilagođeni program za ispravljanje pogrešaka koji koristi korisna sučelja koja nudi JDI. Istodobno smo u program za ispravljanje pogrešaka dodali i koračnu sposobnost.

Kako je ovo bio samo uvod u JDI, preporučljivo je pogledati implementacije drugih sučelja dostupnih pod JDI API-jem.

Kao i obično, sve implementacije koda dostupne su na GitHubu.


$config[zx-auto] not found$config[zx-overlay] not found