Daljinsko ispravljanje pogrešaka Java aplikacije

1. Pregled

Otklanjanje pogrešaka u udaljenom Java programu može biti korisno u više slučajeva.

U ovom uputstvu ćemo otkriti kako to učiniti pomoću JDK-ovog alata.

2. Prijava

Počnimo s pisanjem prijave. Pokrenut ćemo ga na udaljenom mjestu i lokalno ga ispraviti putem ovog članka:

javna klasa OurApplication {private static String staticString = "Statički niz"; private String instanceString; javna statička 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); } javni String buildInstanceString (int broj) {return broj + ". String String!"; }} 

3. JDWP: Java protokol za ispravljanje pogrešaka

The Java protokol za ispravljanje pogrešakaje protokol koji se u Javi koristi za komunikaciju između ispravljača i otklanjanja pogrešaka. Program za otklanjanje pogrešaka je aplikacija koja se otklanja pogreškama, dok je program za uklanjanje pogrešaka aplikacija ili postupak koji se povezuje s aplikacijom koja se otklanja pogreške.

Obje aplikacije rade ili na istom stroju ili na različitim strojevima. Usredotočit ćemo se na ovo drugo.

3.1. Mogućnosti JDWP-a

Koristit ćemo JDWP u argumentima JVM naredbenog retka prilikom pokretanja aplikacije za otklanjanje pogrešaka.

Za njegovo pozivanje potreban je popis mogućnosti:

  • prijevoz je jedina potpuno potrebna opcija. Definira koji će transportni mehanizam koristiti. dt_shmem radi samo na sustavu Windows i ako se oba procesa izvode na istom stroju dok dt_socket kompatibilan je sa svim platformama i omogućuje pokretanje procesa na različitim strojevima
  • poslužitelju nije obavezna opcija. Ova zastavica, kada je uključena, definira način na koji se veže za program za ispravljanje pogrešaka. Ili izlaže postupak putem adrese definirane u adresa opcija. Inače, JDWP izlaže zadani
  • obustaviti definira treba li JVM suspendirati i pričekati da se program za ispravljanje pogrešaka priključi ili ne
  • adresa je opcija koja sadrži adresu, općenito priključak, koji je otkrio otklanjač pogrešaka. Također može predstavljati adresu prevedenu kao niz znakova (poput javadebug ako koristimo poslužitelj = y bez pružanja adresa na sustavu Windows)

3.2. Zapovjedništvo za lansiranje

Počnimo s pokretanjem udaljene aplikacije. Pružit ćemo sve ranije navedene opcije:

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

Do Jave 5, argument JVM runjdwp morali koristiti zajedno s drugom opcijom otklanjanje pogrešaka:

java -Xdebug -Xrunjdwp: transport = dt_socket, poslužitelj = y, suspend = n, adresa = 8000

Ovaj način korištenja JDWP-a i dalje je podržan, ali će se odustati u budućim izdanjima. Radije ćemo upotrijebiti noviju notaciju kad god je to moguće.

3.3. Od Jave 9

Napokon, jedna od mogućnosti JDWP-a promijenila se izdavanjem verzije 9 Jave. Ovo je prilično mala promjena jer se odnosi samo na jednu opciju, ali učinit će promjenu ako pokušavamo otkloniti pogreške u udaljenoj aplikaciji.

Ova promjena utječe na način adresa ponaša se za udaljene aplikacije. Stariji zapis adresa = 8000 odnosi se samo na lokalnihost. Da bismo postigli staro ponašanje, upotrijebit ćemo zvjezdicu s dvotačkom kao prefiksom adrese (npr adresa = *: 8000).

Prema dokumentaciji, ovo nije sigurno i preporučuje se navođenje IP adrese programa za ispravljanje pogrešaka kad god je to moguće:

java -agentlib: jdwp = transport = dt_socket, poslužitelj = y, suspend = n, adresa = 127.0.0.1: 8000

4. JDB: Program za ispravljanje pogrešaka Java

JDB, Java program za ispravljanje pogrešaka, alat je uključen u JDK zamišljen da pruži prikladan klijent za uklanjanje pogrešaka iz naredbenog retka.

Za pokretanje JDB-a koristit ćemo priložiti način rada. Ovaj način spaja JDB na pokrenuti JVM. Postoje i drugi načini rada, poput slušati ili trčanje ali su uglavnom prikladni za otklanjanje pogrešaka u lokalno pokrenutoj aplikaciji:

jdb -attach 127.0.0.1:8000> Inicijalizacija jdb ... 

4.1. Točke prijeloma

Nastavimo stavljanjem nekih prijelomnih točaka u aplikaciju predstavljenu u odjeljku 1.

Postavit ćemo točku prekida na konstruktor:

> zaustavite se u OurApplication. 

Postavit ćemo još jedan u statičkoj metodi glavni, koristeći potpuno kvalificirani naziv Niz razred:

> zaustavite se u OurApplication.main (java.lang.String []) 

Konačno, zadnju ćemo postaviti na metodu instance buildInstanceString:

> zaustavite se u OurApplication.buildInstanceString (int) 

Sada bismo trebali primijetiti zaustavljanje poslužiteljske aplikacije i ispis sljedećeg u našoj konzoli za ispravljanje pogrešaka:

> Učitavanje točke prekida: "thread = main", OurApplication. (), Linija = 11 bci = 0 

Dodajmo sada točku prekida na određenu liniju, onu gdje je varijabla app.instanceString se tiska:

> zaustavite se na OurApplication: 7 

Primjećujemo to na koristi se nakon Stop umjesto u kada je točka prekida definirana na određenoj liniji.

4.2. Navigacija i procjena

Sad kad smo postavili svoje prijelomne točke, poslužimo se nast da nastavimo izvršavanje naše niti dok ne dosegnemo točku prekida na liniji 7.

U konzoli bismo trebali vidjeti sljedeće:

> Učitavanje točke prekida: "thread = main", OurApplication.main (), line = 7 bci = 17 

Podsjećanja radi, zaustavili smo se na retku koji sadrži sljedeći dio koda:

System.out.println (app.instanceString); 

Zaustavljanje na ovoj liniji moglo se izvršiti i zaustavljanjem na glavni metoda i tipkanje korak dvaput. korak izvršava trenutni redak koda i zaustavlja program za ispravljanje pogrešaka izravno na sljedećem retku.

Sad kad smo stali, debugee procjenjuje naše staticString, app‘S instanceString, lokalna varijabla ja i na kraju pogledavši kako vrednovati druge izraze.

Ispisujmo staticField na konzolu:

> eval OurApplication.staticString OurApplication.staticString = "Statički niz" 

Izričito stavljamo ime klase ispred statičkog polja.

Ajmo sada ispisati polje instance app:

> eval app.instanceString app.instanceString = "68741. String niza!" 

Dalje, pogledajmo varijablu ja:

> ispis i i = 68741 

Za razliku od ostalih varijabli, lokalne varijable ne trebaju navesti klasu ili instancu. To također možemo vidjeti ispis ima potpuno isto ponašanje kao eval: oboje procjenjuju izraz ili varijablu.

Procijenit ćemo novu instancu NašaPrimjena za koji smo proslijedili cijeli broj kao parametar konstruktora:

> ispisati novu našuApplication (10) .instanceString novu našuApplication (10) .instanceString = "10. Instance String!" 

Sad kad smo procijenili sve varijable koje su nam trebale, htjet ćemo izbrisati prije postavljene točke prekida i pustiti da nit nastavi s obradom. Da bismo to postigli, poslužit ćemo se naredbom čisto nakon čega slijedi identifikator točke prekida.

Identifikator je potpuno isti kao onaj koji je ranije korišten s naredbom Stop:

> obriši OurApplication: 7 Uklonjeno: točka prekida OurApplication: 7 

Upotrijebit ćemo kako bismo provjerili je li točka prekida ispravno uklonjena čisto bez argumenata. Ovo će prikazati popis postojećih točaka prekida bez one koju smo upravo izbrisali:

> jasno postavljene točke prekida: točka prekida OurApplication. točka prekida OurApplication.buildInstanceString (int) točka prijeloma OurApplication.main (java.lang.String []) 

5. Zaključak

U ovom brzom članku otkrili smo kako koristiti JDWP zajedno s JDB, oba JDK alata.

Više informacija o alatima naravno može se naći u njihovim odgovarajućim referencama: JDWP-ima i JDB-ima - kako bi se dublje ušlo u alat.