Java Application ekstern feilsøking

1. Oversikt

Feilsøking av et eksternt Java-program kan være nyttig i mer enn ett tilfelle.

I denne opplæringen vil vi oppdage hvordan du gjør det ved hjelp av JDKs verktøy.

2. Søknaden

La oss starte med å skrive en søknad. Vi kjører den på et eksternt sted og feilsøker det lokalt gjennom denne artikkelen:

offentlig klasse OurApplication {private static String staticString = "Statisk streng"; privat streng forekomstString; 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); }} offentlig OurApplication (int index) {this.instanceString = buildInstanceString (index); } public String buildInstanceString (int number) {return number + ". Instance String!"; }} 

3. JDWP: Java Debug Wire Protocol

De Java Debug Wire Protocoler en protokoll som brukes i Java for kommunikasjon mellom en feilsøkingsmann og en feilsøkingsprogram. Feilsøkingsprogrammet er applikasjonen som feilsøkes mens feilsøkingsprogrammet er et program eller en prosess som kobles til applikasjonen som feilsøkes.

Begge applikasjonene kjøres enten på samme maskin eller på forskjellige maskiner. Vi vil fokusere på sistnevnte.

3.1. JDWPs alternativer

Vi bruker JDWP i JVM-kommandolinjeargumentene når vi starter feilsøkingsprogrammet.

Påkallingen krever en liste over alternativer:

  • transportere er det eneste helt nødvendige alternativet. Den definerer hvilken transportmekanisme som skal brukes. dt_shmem fungerer bare på Windows, og hvis begge prosessene kjører på samme maskin samtidig som dt_socket er kompatibel med alle plattformer og lar prosessene kjøre på forskjellige maskiner
  • server er ikke et obligatorisk alternativ. Når dette flagget er på, defineres det hvordan det festes til feilsøkingsprogrammet. Enten avslører den prosessen gjennom adressen som er definert i adresse alternativ. Ellers avslører JDWP en standard
  • utsette definerer om JVM skal suspendere og vente på at en feilsøkingsenhet kobles til eller ikke
  • adresse er alternativet som inneholder adressen, vanligvis en port, eksponert av debuggee. Den kan også representere en adresse oversatt som en streng med tegn (som f.eks javadebug hvis vi bruker server = y uten å gi en adresse på Windows)

3.2. Start kommandoen

La oss starte med å starte den eksterne applikasjonen. Vi gir alle alternativene som er oppført tidligere:

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

Inntil Java 5, JVM-argumentet runjdwp måtte brukes sammen med det andre alternativet feilsøke:

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

Denne måten å bruke JDWP på er fortsatt støttet, men vil bli droppet i fremtidige utgivelser. Vi foretrekker bruk av den nyere notasjonen når det er mulig.

3.3. Siden Java 9

Endelig har et av alternativene til JDWP endret seg med utgivelsen av versjon 9 av Java. Dette er ganske liten endring siden det bare gjelder ett alternativ, men vil gjøre en forskjell hvis vi prøver å feilsøke et eksternt program.

Denne endringen påvirker veien adresse oppfører seg for eksterne applikasjoner. Den eldre notasjonen adresse = 8000 gjelder bare for lokal vert. For å oppnå den gamle oppførselen bruker vi en stjerne med et kolon som prefiks for adressen (f.eks adresse = *: 8000).

I følge dokumentasjonen er dette ikke sikkert, og det anbefales å spesifisere feilsøkings-IP-adressen når det er mulig:

java -agentlib: jdwp = transport = dt_socket, server = y, suspendere = n, adresse = 127.0.0.1: 8000

4. JDB: Java Debugger

JDB, Java Debugger, er et verktøy som er inkludert i JDK som er utviklet for å gi en praktisk feilsøkingsklient fra kommandolinjen.

For å starte JDB bruker vi feste modus. Denne modusen fester JDB til en JVM som kjører. Andre løpemodi finnes, for eksempel lytte eller løpe men er mest praktisk når du feilsøker et lokalt kjørende program:

jdb -feste 127.0.0.1:8000> Initialisere jdb ... 

4.1. Breakpoints

La oss fortsette med å sette noen bruddpunkter i applikasjonen presentert i del 1.

Vi setter et bruddpunkt på konstruktøren:

> stopp i vår søknad. 

Vi setter en annen i den statiske metoden hoved-, ved å bruke det fullt kvalifiserte navnet på String klasse:

> stopp i OurApplication.main (java.lang.String []) 

Til slutt setter vi den siste på forekomstmetoden buildInstanceString:

> stopp i OurApplication.buildInstanceString (int) 

Vi bør nå legge merke til at serverapplikasjonen stopper og at følgende skrives ut i feilsøkingskonsollen vår:

> Breakpoint hit: "thread = main", OurApplication. (), Line = 11 bci = 0 

La oss nå legge til et brytpunkt på en bestemt linje, den der variabelen app.instanceString blir skrevet ut:

> stopp ved OurApplication: 7 

Vi merker det brukes etter Stoppe i stedet for i når brytpunktet er definert på en bestemt linje.

4.2. Naviger og evaluer

Nå som vi har satt brytepunktene, la oss bruke det forts for å fortsette kjøringen av tråden vår til vi når brytpunktet på linje 7.

Vi skal se følgende skrives ut i konsollen:

> Breakpoint hit: "thread = main", OurApplication.main (), line = 7 bci = 17 

Som en påminnelse har vi stoppet på linjen som inneholder følgende kode:

System.out.println (app.instanceString); 

Å stoppe på denne linjen kunne også vært gjort ved å stoppe på hoved- metode og skriving steg to ganger. steg kjører den nåværende kodelinjen og stopper feilsøkingsprogrammet direkte på neste linje.

Nå som vi har stoppet, evaluerer flyktningen vår staticString, den app‘S instansestreng, den lokale variabelen Jeg og til slutt ta en titt på hvordan man kan evaluere andre uttrykk.

La oss skrive ut staticField til konsollen:

> eval OurApplication.staticString OurApplication.staticString = "Statisk streng" 

Vi setter eksplisitt navnet på klassen foran det statiske feltet.

La oss nå skrive ut forekomstfeltet til app:

> eval app.instanceString app.instanceString = "68741. Forekomststreng!" 

La oss se variabelen Jeg:

> skriv ut i i = 68741 

I motsetning til de andre variablene krever lokale variabler ikke å spesifisere en klasse eller en forekomst. Det kan vi også se skrive ut har nøyaktig samme oppførsel som eval: begge vurderer et uttrykk eller en variabel.

Vi vil evaluere en ny forekomst av Vår søknad som vi har passert et heltall for som en konstruktorparameter:

> skriv ut ny OurApplication (10) .instanceString ny OurApplication (10) .instanceString = "10. Instance String!" 

Nå som vi har evaluert alle variablene vi trengte, vil vi slette brytepunktene som er angitt tidligere og la tråden fortsette behandlingen. For å oppnå dette bruker vi kommandoen klar etterfulgt av bruddpunktets identifikator.

Identifikatoren er nøyaktig den samme som den som ble brukt tidligere med kommandoen Stoppe:

> tøm OurApplication: 7 Fjernet: breakpoint OurApplication: 7 

For å bekrefte om bruddpunktet er riktig fjernet, bruker vi klar uten argumenter. Dette vil vise listen over eksisterende brytepunkter uten den vi nettopp har slettet:

> tøm pausepunkter: brytpunkt OurApplication. brytpunkt OurApplication.buildInstanceString (int) breakpoint OurApplication.main (java.lang.String []) 

5. Konklusjon

I: i denne raske artikkelen har vi oppdaget hvordan du bruker JDWP sammen med JDB, begge JDK-verktøyene.

Mer informasjon om verktøyene finner du selvfølgelig i deres respektive referanser: JDWP og JDB - for å gå dypere inn i verktøyet.


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