Diaľkové ladenie aplikácií Java

1. Prehľad

Ladenie vzdialenej aplikácie Java môže byť užitočné vo viac ako jednom prípade.

V tomto tutoriále zistíme, ako to urobiť pomocou nástrojov JDK.

2. Žiadosť

Začnime písaním žiadosti. Spustíme ho na vzdialenom mieste a lokálne ho odladíme prostredníctvom tohto článku:

verejná trieda OurApplication {private static String staticString = "Static String"; private String instanceString; public static void main (String [] args) {for (int i = 0; i <1_000_000_000; i ++) {OurApplication app = new OurApplication (i); System.out.println (app.instanceString); }} public OurApplication (int index) {this.instanceString = buildInstanceString (index); } public String buildInstanceString (int číslo) {návratové číslo + ". Reťazec inštancie!"; }} 

3. JDWP: Protokol Java Debug Wire

The Java Debug Wire Protocolje protokol používaný v Jave na komunikáciu medzi debuggee a debuggerom. Ladiacim nástrojom je ladená aplikácia, zatiaľ čo ladiacim programom je aplikácia alebo proces pripájajúci sa k ladenej aplikácii.

Obe aplikácie bežia na rovnakom stroji alebo na rôznych strojoch. Zameriame sa na to druhé.

3.1. Možnosti JDWP

Pri spustení aplikácie debuggee použijeme JDWP v argumentoch príkazového riadku JVM.

Jeho vyvolanie si vyžaduje zoznam možností:

  • doprava je jediná plne požadovaná možnosť. Definuje, ktorý transportný mechanizmus sa má použiť. dt_shmem funguje iba v systéme Windows a ak sú oba procesy spustené na rovnakom počítači zatiaľ čo dt_socket je kompatibilný so všetkými platformami a umožňuje procesom bežať na rôznych strojoch
  • server nie je povinnou možnosťou. Tento príznak, ak je zapnutý, definuje spôsob jeho pripojenia k debuggeru. Buď vystavuje proces prostredníctvom adresy definovanej v adresa možnosť. V opačnom prípade JDWP vystaví predvolený
  • pozastaviť definuje, či sa má JVM pozastaviť a čakať na pripojenie ladiaceho programu alebo nie
  • adresa je voľba obsahujúca adresu, obvykle port, vystavený ladiacim programom. Môže tiež predstavovať adresu preloženú ako reťazec znakov (napríklad javadebug ak použijeme server = r bez poskytnutia adresa vo Windows)

3.2. Spustite príkaz

Začnime spustením vzdialenej aplikácie. Poskytneme všetky možnosti uvedené vyššie:

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

Až do Javy 5, argument JVM runjdwp muselo byť použité spolu s druhou možnosťou ladiť:

java -Xdebug -Xrunjdwp: transport = dt_socket, server = y, suspend = n, adresa = 8000

Tento spôsob použitia JDWP je stále podporovaný, ale v budúcich vydaniach bude zrušený. Pokiaľ je to možné, uprednostníme použitie novšej notácie.

3.3. Od Javy 9

Napokon sa jedna z možností JDWP zmenila s vydaním verzie 9 Java. Toto je dosť malá zmena, pretože sa týka iba jednej možnosti, ale bude mať rozdiel, ak sa pokúsime odladiť vzdialenú aplikáciu.

Táto zmena má vplyv na cestu adresa sa chová pre vzdialené aplikácie. Starší zápis adresa = 8000 platí iba pre localhost. Na dosiahnutie starého správania použijeme ako predponu adresy hviezdičku s dvojbodkou (napr adresa = *: 8000).

Podľa dokumentácie to nie je bezpečné a odporúča sa vždy, keď je to možné, uviesť adresu IP debuggera:

java -agentlib: jdwp = transport = dt_socket, server = y, suspend = n, adresa = 127.0.0.1: 8000

4. JDB: Java Debugger

JDB, Java Debugger, je nástroj zahrnutý v JDK koncipovaný na poskytovanie pohodlného debugger klienta z príkazového riadku.

Na spustenie JDB použijeme pripojiť režim. Tento režim pripája JDB k spustenému JVM. Existujú aj ďalšie prevádzkové režimy, ako napr počúvaj alebo bežať ale väčšinou sú pohodlné pri ladení lokálne spustenej aplikácie:

jdb -attach 127.0.0.1:8000> Inicializuje sa jdb ... 

4.1. Hraničné hodnoty

Pokračujme uvedením niektorých hraničných bodov do aplikácie uvedenej v časti 1.

Nastavíme bod prerušenia na konštruktore:

> zastavte sa v OurApplication. 

V statickej metóde nastavíme ďalšiu hlavnýpomocou plne kvalifikovaného názvu servera String trieda:

> zastávka v OurApplication.main (java.lang.String []) 

Nakoniec nastavíme posledný na inštančnú metódu buildInstanceString:

> zastaviť v OurApplication.buildInstanceString (int) 

Teraz by sme si mali všimnúť zastavenie serverovej aplikácie a to, čo sa tlačí v našej konzole ladiaceho programu:

> Hitpoint break: "thread = main", OurApplication. (), Line = 11 bci = 0 

Teraz pridajme bod prerušenia na konkrétny riadok, do ktorého je premenná reťazec aplikácie práve sa tlačí:

> zastavte sa na OurApplication: 7 

To si všimneme o sa používa po zastav namiesto v keď je bod zlomu definovaný na konkrétnom riadku.

4.2. Navigácia a hodnotenie

Teraz, keď sme stanovili svoje hraničné hodnoty, využime to pokr pokračovať vo vykonávaní nášho vlákna, kým sa nedostaneme k bodu zlomu na riadku 7.

V konzole by sme mali vidieť nasledujúce:

> Bod zlomu: "thread = main", OurApplication.main (), line = 7 bci = 17 

Pripomíname, že sme sa zastavili na riadku obsahujúcom nasledujúci kód:

System.out.println (app.instanceString); 

Zastavenie na tejto linke sa mohlo uskutočniť aj zastavením na ceste hlavný metóda a písanie na stroji krok dvakrát. krok vykoná aktuálny riadok kódu a zastaví ladiaci program priamo na nasledujúcom riadku.

Teraz, keď sme prestali, ladiaci program hodnotí naše staticString, aplikácia‘S instanceString, lokálna premenná i a nakoniec sa pozrieme na to, ako hodnotiť ďalšie výrazy.

Poďme tlačiť staticField do konzoly:

> eval OurApplication.staticString OurApplication.staticString = "statický reťazec" 

Názov triedy sme výslovne vložili pred statické pole.

Poďme si vytlačiť pole inštancie aplikácia:

> eval app.instanceString app.instanceString = "68741. Reťazec inštancie!" 

Ďalej sa pozrime na premennú i:

> tlač i i = 68741 

Na rozdiel od iných premenných miestne premenné nevyžadujú zadanie triedy alebo inštancie. Vidíme to aj my tlačiť má úplne rovnaké správanie ako eval: obaja hodnotia výraz alebo premennú.

Zhodnotíme novú inštanciu NašaAplikácia pre ktoré sme zadali celé číslo ako parameter konštruktora:

> vytlačiť novú OurApplication (10) .instanceString novú OurApplication (10) .instanceString = "10. Reťazec inštancie!" 

Teraz, keď sme vyhodnotili všetky premenné, ktoré sme potrebovali, budeme chcieť vymazať zarážky nastavené skôr a nechať vlákno pokračovať v jeho spracovaní. Aby sme to dosiahli, použijeme príkaz jasný za ktorým nasleduje identifikátor prerušenia.

Identifikátor je úplne rovnaký ako identifikátor použitý skôr v príkaze zastav:

> Vymazať OurApplication: 7 Odstránené: bod zlomu OurApplication: 7 

Použijeme na overenie, či bol bod prerušenia správne odstránený jasný bez argumentov. Zobrazí sa zoznam existujúcich hraničných bodov bez toho, ktorý sme práve odstránili:

> Vymazať nastavený bod prerušenia: bod prerušenia OurApplication. breakpoint OurApplication.buildInstanceString (int) breakpoint OurApplication.main (java.lang.String []) 

5. Záver

V tomto rýchlom článku sme objavili, ako používať JDWP spolu s JDB, obidvomi nástrojmi JDK.

Viac informácií o nástrojoch nájdete samozrejme v ich príslušných referenciách: JDWP a JDB - aby sme sa dostali hlbšie do oblasti nástrojov.