Java alkalmazás távoli hibakeresése

1. Áttekintés

A távoli Java-alkalmazások hibakeresése több esetben is hasznos lehet.

Ebben az oktatóanyagban megtudhatjuk, hogyan lehet ezt megtenni a JDK eszközeivel.

2. Az alkalmazás

Kezdjük egy pályázat megírásával. Futtatjuk egy távoli helyen, és helyi hibakeresést végezünk a cikk segítségével:

public class OurApplication {private static String staticString = "Static String"; privát String instanceString; public static void main (String [] args) {for (int i = 0; i <1_000_000_000; i ++) {OurApplication alkalmazás = új OurApplication (i); System.out.println (app.instanceString); }} public OurApplication (int index) {this.instanceString = buildInstanceString (index); } public String buildInstanceString (int szám) {visszatérési szám + ". Példány karakterlánc!"; }} 

3. JDWP: A Java Debug Wire protokoll

A Java Debug Wire Protocolegy olyan protokoll, amelyet a Java használ a debuggee és a debugger közötti kommunikációra. A hibakereső a hibakeresés alatt álló alkalmazás, míg a hibakereső a hibakeresés alatt álló alkalmazáshoz csatlakozó alkalmazás vagy folyamat.

Mindkét alkalmazás ugyanazon a gépen vagy különböző gépeken fut. Utóbbira fogunk koncentrálni.

3.1. A JDWP opciói

A JDWP-t a JVM parancssori argumentumokban fogjuk használni, amikor elindítjuk a hibakereső alkalmazást.

Meghívásához a következő lehetőségek listája szükséges:

  • szállítás az egyetlen teljesen szükséges lehetőség. Meghatározza, hogy melyik szállítási mechanizmust használja. dt_shmem csak Windows rendszeren működik, és ha mindkét folyamat ugyanazon a gépen fut míg dt_socket kompatibilis az összes platformmal, és lehetővé teszi a folyamatok különböző gépeken történő futtatását
  • szerver nem kötelező opció. Ha be van kapcsolva, akkor ez a jelző meghatározza a hibakeresőhöz való kapcsolódás módját. Vagy felfedi a folyamatot a címben megadott címen keresztül cím választási lehetőség. Ellenkező esetben a JDWP kitesz egy alapértelmezettet
  • függessze fel meghatározza, hogy a JVM-nek fel kell-e függesztenie és várnia kell egy hibakereső csatolását vagy sem
  • cím az opció, amely tartalmazza a hibakereső által kitett címet, általában egy portot. Ez egy címet is képviselhet karakterláncként (például javadebug ha használjuk szerver = y anélkül, hogy egy cím Windows rendszeren)

3.2. Indítsa el a Parancsot

Kezdjük a távoli alkalmazás elindításával. Megadjuk az összes korábban felsorolt ​​lehetőséget:

java -agentlib: jdwp = transport = dt_socket, server = y, suspend = n, address = 8000 OurApplication 

Java 5-ig a JVM argumentum runjdwp a másik lehetőséggel együtt kellett használni hibakeresés:

java -Xdebug -Xrunjdwp: szállítás = dt_socket, szerver = y, felfüggesztés = n, cím = 8000

A JDWP használatának ez a módja továbbra is támogatott, de a jövőbeni kiadásokban elvetik. Lehetőség szerint előnyben részesítjük az újabb jelölések használatát.

3.3. Mivel a Java 9

Végül a JDWP egyik lehetősége megváltozott a Java 9-es verziójának kiadásával. Ez meglehetősen csekély változás, mivel csak egy opciót érint, de változást hoz, ha egy távoli alkalmazást próbálunk hibakeresni.

Ez a változás befolyásolja az utat cím távoli alkalmazások esetén viselkedik. A régebbi jelölés cím = 8000 csak a helyi kiszolgáló. A régi viselkedés elérése érdekében kettőspontot tartalmazó csillagot fogunk használni a cím előtagaként (pl cím = *: 8000).

A dokumentáció szerint ez nem biztonságos, ezért ajánlatos a hibakereső IP-címét megadni, amikor csak lehetséges:

java -agentlib: jdwp = transport = dt_socket, szerver = y, suspend = n, address = 127.0.0.1: 8000

4. JDB: A Java hibakereső

A JDB, a Java hibakereső, egy olyan eszköz, amelyet a JDK tartalmaz, amelynek célja a kényelmesebb hibakereső kliens biztosítása a parancssorból.

A JDB elindításához a csatolni mód. Ez a mód a JDB-t egy futó JVM-hez csatolja. Egyéb futási módok léteznek, például hallgat vagy fuss de többnyire kényelmesek egy helyben futó alkalmazás hibakeresésénél:

jdb -attach 127.0.0.1:8000> A jdb inicializálása ... 

4.1. Töréspontok

Folytassuk néhány töréspont beillesztésével az 1. szakaszban bemutatott alkalmazásba.

Beállítunk egy töréspontot a kivitelezőn:

> álljon meg a mi alkalmazásunkban. 

A statikus módszerrel beállítunk egy másikat fő-, a teljes minősítésű név használatával Húr osztály:

> állj meg a OurApplication.main fájlban (java.lang.String []) 

Végül beállítjuk az utolsó példánymódszert buildInstanceString:

> megáll a OurApplication.buildInstanceString (int) 

Most észre kell vennünk, hogy a kiszolgálóalkalmazás leáll, és a következőket nyomtatják a hibakereső konzolunkba:

> Töréspont találat: "thread = main", OurApplication. (), Line = 11 bci = 0 

Most adjunk hozzá egy töréspontot egy adott vonalhoz, azt, ahol a változó app.instanceString nyomtatás alatt áll:

> álljon meg a mi alkalmazásunknál: 7 

Ezt észrevesszük nál nél után használják álljon meg ahelyett ban ben amikor a töréspontot egy adott vonalon definiálják.

4.2. Navigálás és értékelés

Most, hogy beállítottuk a töréspontjainkat, használjuk folytatás hogy folytassuk szálunk végrehajtását, amíg el nem érjük a töréspontot a 7. vonalon.

A következőket kell látnunk nyomtatni a konzolon:

> Töréspont találat: "thread = main", OurApplication.main (), line = 7 bci = 17 

Emlékeztetőül megálltunk a következő kódot tartalmazó soron:

System.out.println (app.instanceString); 

Ezen a vonalon történő megállást a megállónál is meg lehetett volna tenni fő- módszer és gépelés lépés kétszer. lépés végrehajtja az aktuális kódsort, és közvetlenül a következő sorban állítja le a hibakeresőt.

Most, hogy abbahagytuk, a hibakereső értékeli a dolgunkat staticString, a kb’S instanceString, a helyi változó én és végül egy pillantást vetünk a többi kifejezés értékelésére.

Nyomtassunk staticField a konzolhoz:

> eval OurApplication.staticString OurApplication.staticString = "Statikus karakterlánc" 

Az osztály nevét kifejezetten a statikus mező elé tesszük.

Most nyomtassuk ki a kb:

> eval app.instanceString app.instanceString = "68741. Példány-karakterlánc!" 

Ezután nézzük meg a változót én:

> i nyomtatás = 68741 

A többi változóval ellentétben a helyi változók nem igényelnek osztályt vagy példányt. Ezt is láthatjuk nyomtatás pontosan ugyanúgy viselkedik, mint eval: mindkettő értékel egy kifejezést vagy egy változót.

Értékelni fogjuk a A mi alkalmazásunk amelyhez egy egész számot adtunk meg konstruktorként:

> nyomtassa ki az új OurApplication (10) .instanceString új OurApplication (10) .instanceString = "10. Példány karakterlánc!" 

Miután kiértékeltük az összes szükséges változót, törölni akarjuk a korábban beállított töréspontokat, és hagyjuk, hogy a szál folytassa a feldolgozását. Ennek eléréséhez a parancsot fogjuk használni egyértelmű amelyet a töréspont azonosítója követ.

Az azonosító pontosan megegyezik a paranccsal korábban használt azonosítóval álljon meg:

> törölje a mi Alkalmazásunkat: 7 Eltávolítva: töréspont A mi alkalmazásunk: 7 

Annak ellenőrzésére, hogy a töréspontot megfelelően eltávolították-e, használjuk egyértelmű érvek nélkül. Ez megjeleníti a meglévő töréspontok listáját anélkül, hogy az imént töröltük volna:

> egyértelmű töréspontok beállítása: töréspont OurApplication. töréspont OurApplication.buildInstanceString (int) töréspont OurApplication.main (java.lang.String []) 

5. Következtetés

Ez a rövid cikk felfedeztük, hogyan lehet a JDWP-t használni a JDB-vel, mindkét JDK eszközzel.

A szerszámozásról további információk természetesen megtalálhatók a megfelelő referenciákban: JDWP-k és JDB-k - hogy jobban belemerülhessünk az eszközökbe.