Bevezetés a Java hibakeresési felületbe (JDI)
1. Áttekintés
Kíváncsi lehetünk arra, hogy az olyan széles körben elismert IDE-k, mint az IntelliJ IDEA és az Eclipse, hogyan hajtják végre a hibakeresési szolgáltatásokat. Ezek az eszközök nagyban támaszkodnak a Java Platform Debugger Architecture-re (JPDA).
Ebben a bevezető cikkben a JPDA alatt elérhető Java Debug Interface API-t (JDI) tárgyaljuk.
Ugyanabban az időben, írunk egy egyedi hibakereső programot lépésről lépésre ismerkedjünk meg a praktikus JDI interfészekkel.
2. Bevezetés a JPDA-ba
A Java Platform Debugger Architecture (JPDA) egy jól megtervezett interfészek és protokollok összessége, amelyeket a Java hibakereséséhez használnak.
Három speciálisan tervezett felületet kínál az egyedi hibakeresők megvalósításához az asztali rendszerek fejlesztői környezetéhez.
Először is, a Java Virtual Machine Tool Interface (JVMTI) segít kölcsönhatásban és ellenőrizni a JVM-ben futó alkalmazások futtatását.
Ezután ott van a Java Debug Wire Protocol (JDWP), amely meghatározza a tesztelt alkalmazás (debuggee) és a debugger között használt protokollt.
Végül a Java Debug Interface (JDI) a hibakereső alkalmazás megvalósítására szolgál.
3. Mi az JDI?
A Java Debug Interface API a Java által biztosított interfészek összessége a hibakereső kezelőfelületének megvalósításához. A JDI a JPDA legmagasabb rétege.
A JDI-vel felépített hibakereső bármilyen JPV-t támogató JVM-ben futó alkalmazásokat hibakeresésre képes. Ugyanakkor a hibakeresés bármely rétegébe bekapcsolhatjuk.
Lehetővé teszi a virtuális gép és annak állapotának elérését, valamint a hibakereső változóihoz való hozzáférést. Ugyanakkor lehetővé teszi a töréspontok, a lépések, az ellenőrzési pontok és a szálak kezelését.
4. Beállítás
Két külön programra lesz szükségünk - egy hibakeresőre és egy hibakeresőre -, hogy megértsük a JDI megvalósításait.
Először írunk egy mintaprogramot hibakeresőként.
Hozzunk létre egy JDIExampleDuguggee osztály néhány Húr változók és println nyilatkozatok:
public class JDIExampleDebuggee {public static void main (String [] args) {String jpda = "Java Platform Debugger Architecture"; System.out.println ("Sziasztok mindenkit, üdvözlünk a" + jpda-ban); // adjon itt töréspontot String jdi = "Java Debug Interface"; // adjon itt töréspontot, és lépjen ide is String text = "Ma belemerülünk" + jdi; System.out.println (szöveg); }}
Ezután írunk egy hibakereső programot.
Hozzunk létre egy JDIExampleDebugger osztály tulajdonságokkal a hibakereső program megtartására (debugClass) és a töréspontok sorszáma (breakPointLines):
public class JDIExampleDebugger {private Class debugClass; private int [] breakPointLines; // szerelők és beállítók}
4.1. LaunchingConnector
Először egy hibakeresőnek csatlakozóra van szüksége a kapcsolat létrehozásához a virtuális géppel (virtuális gép).
Ezután be kell állítanunk a hibakeresőt csatlakozóként fő- érv. Végül az összekötőnek elindítania kell a virtuális gépet a hibakereséshez.
Ehhez a JDI biztosítja a Bootstrap osztály, amely megadja a LaunchingConnector. A LaunchingConnector megadja az alapértelmezett argumentumok térképét, amelyben beállíthatjuk a fő- érv.
Ezért tegyük hozzá a connectAndLaunchVM módszer a JDIDebuggerExample osztály:
public VirtualMachine connectAndLaunchVM () dobja a Kivételt {LaunchingConnector launchingConnector = Bootstrap.virtualMachineManager () .defaultConnector (); Map argumentumok = launchingConnector.defaultArguments (); argumentumok.get ("main"). setValue (debugClass.getName ()); return launchingConnector.launch (érvek); }
Most hozzáadjuk a fő- módszer a JDIDebuggerExample osztály debug a JDIExampleDuguggee:
public static void main (String [] args) dobja a {JDIExampleDebugger debuggerInstance = new JDIExampleDebugger () kivételt; debuggerInstance.setDebugClass (JDIExampleDebuggee.class); int [] breakPoints = {6, 9}; debuggerInstance.setBreakPointLines (breakPoints); VirtualMachine vm = null; próbáld ki a {vm = debuggerInstance.connectAndLaunchVM () parancsot; vm.resume (); } catch (e kivétel) {e.printStackTrace (); }}
Állítsuk össze mindkét osztályunkat, JDIExampleDuguggee (debuggee) és JDIExampleDebugger (hibakereső):
javac -g -cp "/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/lib/tools.jar" com / baeldung / jdi / *. java
Beszéljük meg a javac itt használt parancs, részletesen.
A -g opció generálja az összes hibakeresési információt amely nélkül láthatjuk AbsentInformationException.
És -cp hozzáadja a eszközök.jar az osztálypályán az osztályok összeállításához. Az összes JDI könyvtár elérhető a következő címen: eszközök.jar a JDK. Ezért feltétlenül adja hozzá a eszközök.jar az osztályban mind az összeállításnál, mind a végrehajtásnál. Ez az, most már készen állunk az egyedi hibakereső végrehajtására JDIExampleDebugger: Vegye figyelembe a „:.” val vel eszközök.jar. Ez kiegészül eszközök.jar a classpath-ra az aktuális futási időre (használja a „;.” -t a Windows-on). A hibakereső program itt történő végrehajtása nem eredményez eredményeket, mivel nem készítettük fel az osztályt a hibakeresésre és nem állítottuk be a töréspontokat. A Virtuális gép osztály rendelkezik a eventRequestManager metódus különféle kérések, például ClassPrepareRequest, BreakpointRequest, és StepEventRequest. Tehát tegyük hozzá a enableClassPrepareRequest módszer a JDIExampleDebugger osztály. Ez leszűrni a JDIExampleDuguggee osztály és lehetővé teszi a ClassPrepareRequest: Egyszer, ClassPrepareRequest a JDIExampleDuguggee osztály engedélyezve van, a virtuális gép eseménysorában megkezdődnek a ClassPrepareEvent. Használata ClassPrepareEvent, megkaphatjuk a töréspont beállításának helyét és létrehozunk egy BreakPointRequest. Ehhez tegyük hozzá a setBreakPoints módszer a JDIExampleDebugger osztály: Eddig felkészítettük az osztályt a hibakeresésre és beállítottuk a töréspontokat. Most el kell kapnunk a BreakPointEvent és megjeleníti a változókat. A JDI biztosítja a StackFrame osztály, hogy megkapja a debuggee összes látható változójának listáját. Ezért tegyük hozzá a displayVariables módszer a JDIExampleDebugger osztály: Ebben a lépésben csak a frissítésre van szükségünk fő- módszere JDIExampleDebugger hogy elkezdjen hibakeresést. Ezért a már tárgyalt módszereket fogjuk használni enableClassPrepareRequest, setBreakPoints, és displayVariables: Most először állítsuk össze a JDIDebuggerExample osztály ismét a már tárgyalt javac parancs. És végül a kimenet megtekintéséhez végrehajtjuk a hibakereső programot az összes módosítással együtt: Hurrá! Sikeresen kijavítottuk a JDIExampleDuguggee osztály. Ugyanakkor megjelenítettük a változók értékeit a töréspont helyein (6. és 9. sorszám). Ezért az egyedi hibakeresőnk készen áll. A hibakereséshez meg kell adni a kódot, és ellenőrizni kell a változók állapotát a következő lépéseknél. Ezért létrehozunk egy lépéskérést a törésponton. Miközben létrehozta a StepRequest, meg kell adnunk a lépés méretét és mélységét. Meghatározzuk STEP_LINE és ÁTLÉP illetőleg. Írjunk egy módszert a lépéskérés engedélyezésére. Az egyszerűség kedvéért kezdjük az utolsó töréspontot (9. sorszám): Most frissíthetjük a fő- módszere JDIExampleDebugger, a lépéskérés engedélyezéséhez, amikor a BreakPointEvent: Hasonló a BreakPointEvent, a változókat a StepEvent. Frissítsük a fő- módszer ennek megfelelően: Végül végrehajtjuk a hibakeresőt, hogy lássuk a változók állapotát, miközben belépünk a kódba: Ha összehasonlítjuk a kimenetet, rájövünk, hogy a hibakereső belépett a 9. sorból, és minden további lépésben megjeleníti a változókat. Ezt észrevehetjük println nyilatkozatai JDIExampleDuguggee osztály nem volt része a hibakereső kimenetnek. Ezért tegyük hozzá a végül záradékunk fő- módszer: Most a hibakereső program végrehajtása hozzáadja a println nyilatkozatok a JDIExampleDuguggee osztály a hibakereső kimenethez: Ebben a cikkben feltártuk a Java Debug Interface (JDI) API-t, amely a Java Platform Debugger Architecture (JPDA) alatt érhető el. Útközben létrehoztunk egy egyedi hibakeresőt, felhasználva a JDI által biztosított praktikus felületeket. Ugyanakkor a hibakeresőhöz léptető képességet is adtunk. Mivel ez csak a JDI bevezetése volt, javasoljuk, hogy nézze meg a JDI API alatt elérhető egyéb interfészek megvalósítását. Szokás szerint az összes kód implementáció elérhető a GitHubon.java -cp "/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/lib/tools.jar :." JDIExampleDebugger
4.2. Bootstrap és ClassPrepareRequest
public void enableClassPrepareRequest (VirtualMachine vm) {ClassPrepareRequest classPrepareRequest = vm.eventRequestManager (). createClassPrepareRequest (); classPrepareRequest.addClassFilter (debugClass.getName ()); classPrepareRequest.enable (); }
4.3. ClassPrepareEvent és BreakpointRequest
public void setBreakPoints (VirtualMachine vm, ClassPrepareEvent esemény) dobja az AbsentInformationException {ClassType classType = (ClassType) esemény.referenceType (); for (int lineNumber: breakPointLines) {Location location = classType.locationsOfLine (lineNumber) .get (0); BreakpointRequest bpReq = vm.eventRequestManager (). CreateBreakpointRequest (hely); bpReq.enable (); }}
4.4. BreakPointEvent és StackFrame
public void displayVariables (LocatableEvent event) az IncompatibleThreadStateException, AbsentInformationException {StackFrame stackFrame = event.thread (). frame (0) dob; if (stackFrame.location (). toString (). tartalmazza (debugClass.getName ())) {Map visibleVariables = stackFrame .getValues (stackFrame.visibleVariables ()); System.out.println ("Változók a" + stackFrame.location (). ToString () + ">" -ban); a (Map.Entry bejegyzéshez: láthatóVariables.entrySet ()) {System.out.println (entry.getKey (). név () + "=" + entry.getValue ()); }}}
5. Debug Target
próbáld ki a {vm = debuggerInstance.connectAndLaunchVM () parancsot; debuggerInstance.enableClassPrepareRequest (vm); EventSet eventSet = null; while (((eventSet = vm.eventQueue (). remove ())! = null) {for (Event event: eventSet) {if (eventPrimex of ClassPrepareEvent) {debuggerInstance.setBreakPoints (vm, (ClassPrepareEvent) esemény); } if (a BreakpointEvent esemény példánya) {debuggerInstance.displayVariables ((BreakpointEvent) esemény); } vm.resume (); }}} catch (VMDisconnectedException e) {System.out.println ("A virtuális gép nincs csatlakoztatva."); } catch (e kivétel) {e.printStackTrace (); }
Változók a com.baeldung.jdi.JDIExampleDebuggee címen: 6> args = a java.lang.String példánya [0] (id = 93) A com.baeldung.jdi.JDIExampleDebuggee: 9> jpda = "Java Platform Debugger Architecture" változók = a java.lang.String [0] (id = 93) példánya A virtuális gép le van választva.
5.1. StepRequest
public void enableStepRequest (VirtualMachine vm, BreakpointEvent event) {// engedélyezi az utolsó töréspont lépéskérését, ha (event.location (). toString (). tartalmazza (debugClass.getName () + ":" + breakPointLines [breakPointLines.length- 1])) {StepRequest stepRequest = vm.eventRequestManager () .createStepRequest (event.thread (), StepRequest.STEP_LINE, StepRequest.STEP_OVER); stepRequest.enable (); }}
if (a BreakpointEvent esemény példánya) {debuggerInstance.enableStepRequest (vm, (BreakpointEvent) esemény); }
5.2. StepEvent
if (a StepEvent esemény példánya) {debuggerInstance.displayVariables ((StepEvent) esemény); }
Változók a com.baeldung.jdi.JDIExampleDebuggee címen: 6> args = a java.lang.String [0] (id = 93) példánya. A com.baeldung.jdi.JDIExampleDebuggee: 9> args = java.lang.String példányai [0] (id = 93) jpda = "Java Platform Debugger Architecture" változók a com.baeldung.jdi.JDIExampleDebuggee címen: 10> args = a java.lang.String példánya [0] (id = 93) jpda = "Java platform Hibakereső architektúra "jdi =" Java hibakeresési felület "Változók a com.baeldung.jdi.JDIExampleDebuggee címen: 11> args = java.lang.String [0] (id = 93) jpda =" Java platform hibakereső architektúra "jdi =" Java hibakereső felület "text =" Ma a Java Debug Interface "változókba merülünk át: com.baeldung.jdi.JDIExampleDebuggee: 12> args = java.lang.String [0] (id = 93) jpda =" változók Java Platform Debugger Architecture "jdi =" Java Debug Interface "text =" Ma belemerülünk a Java Debug Interface-be "A virtuális gép nincs csatlakoztatva.
végül {InputStreamReader olvasó = new InputStreamReader (vm.process (). getInputStream ()); OutputStreamWriter író = új OutputStreamWriter (System.out); char [] buf = új char [512]; olvasó.olvasott (buf); író.írni (buf); író.öblítés (); }
Üdvözlet mindenkinek, Üdvözöljük a Java Platform Debugger Architecture-ben!
7. Következtetés