Ulike måter å fange Java Heap Dumps på

1. Introduksjon

I denne artikkelen vil vi vise forskjellige måter å fange en haugedump i Java.

En heap dump er et øyeblikksbilde av alle objektene som er i minnet i JVM på et bestemt tidspunkt. De er veldig nyttige for å feilsøke minnelekkasjeproblemer og optimalisere minnebruk i Java-applikasjoner.

Heapdumps lagres vanligvis i hprof-filer i binært format. Vi kan åpne og analysere disse filene ved hjelp av verktøy som jhat eller JVisualVM. Også for Eclipse-brukere er det veldig vanlig å bruke MAT.

I de neste avsnittene vil vi gå gjennom flere verktøy og tilnærminger for å generere en heap dump, og vi vil vise de viktigste forskjellene mellom dem.

2. JDK-verktøy

JDK kommer med flere verktøy for å fange dyppedumper på forskjellige måter. Alle disse verktøyene er plassert under søppel mappen i JDK-hjemmekatalogen. Derfor kan vi starte dem fra kommandolinjen så lenge denne katalogen er inkludert i systemstien.

I de neste avsnittene vil vi vise hvordan du bruker disse verktøyene for å fange haugdumper.

2.1. jmap

jmap er et verktøy for å skrive ut statistikk om minne i en kjørende JVM. Vi kan bruke den til lokale eller eksterne prosesser.

For å fange en haug dump ved hjelp av jmap må vi bruke dump alternativ:

jmap -dump: [live], format = b, file = 

Sammen med det alternativet, bør vi spesifisere flere parametere:

  • bo: hvis angitt, skrives det bare ut objekter som har aktive referanser og forkaster de som er klare til å samles inn søppel. Denne parameteren er valgfri
  • format = b: spesifiserer at dumpfilen vil være i binært format. Hvis ikke angitt, er resultatet det samme
  • fil: filen der dumpen skal skrives til
  • pid: id for Java-prosessen

Et eksempel kan være slik:

jmap -dump: live, format = b, file = / tmp / dump.hprof 12587

Husk at vi lett kan få pid av en Java-prosess ved hjelp av jps kommando.

Husk detjmap ble introdusert i JDK som et eksperimentelt verktøy, og det støttes ikke. Derfor kan det i noen tilfeller være å foretrekke å bruke andre verktøy i stedet.

2.2. jcmd

jcmd er et veldig komplett verktøy som fungerer ved å sende kommandoforespørsler til JVM. Vi må bruke den på samme maskin der Java-prosessen kjører.

En av de mange kommandoene er GC.heap_dump. Vi kan bruke den til å få en dyngdump bare ved å spesifisere pid av prosessen og utdatafilbanen:

jcmd GC.heap_dump 

Vi kan utføre den med de samme parametrene som vi brukte før:

jcmd 12587 GC.heap_dump /tmp/dump.hprof

Som med jmap er den genererte dumpen i binært format.

2.3. JVisualVM

JVisualVM er et verktøy med et grafisk brukergrensesnitt som lar oss overvåke, feilsøke og profilere Java-applikasjoner. GUI er enkel, men veldig intuitiv og enkel å bruke.

En av de mange alternativene gjør at vi kan fange en haugedump. Hvis vi høyreklikker på en Java-prosess og velger “Heap Dump” alternativet, vil verktøyet opprette en heap dump og åpne den i en ny fane:

Legg merke til at vi kan finne banen til filen som er opprettet i "Grunnleggende informasjon" seksjon.

Fra og med JDK 9 er ikke Visual VM inkludert i Oracle JDK og Open JDK-distribusjonene. Derfor, hvis vi bruker Java 9 eller nyere versjoner, kan vi få JVisualVM fra Visual VM open source-prosjektstedet.

3. Ta et høydepunkt automatisk

Alle verktøyene vi har vist i de forrige avsnittene, er ment å fange dyppedumper manuelt på et bestemt tidspunkt. I noen tilfeller ønsker vi å få en dyngdump når en java.lang.OutOfMemoryError oppstår, slik at det hjelper oss med å undersøke feilen.

For disse tilfellene, Java tilbyr HeapDumpOnOutOfMemoryError kommandolinjealternativ som genererer en heap dump når en java.lang.OutOfMemoryError blir kastet:

java -XX: + HeapDumpOnOutOfMemoryError

Som standard lagrer den dumpen i en java_pid.hprof filen i katalogen der vi kjører applikasjonen. Hvis vi vil spesifisere en annen fil eller katalog, kan vi sette den i HeapDumpPath alternativ:

java -XX: + HeapDumpOnOutOfMemoryError -XX: HeapDumpPath =

Når applikasjonen går tom for minne ved hjelp av dette alternativet, vil vi kunne se i loggene den opprettede filen som inneholder bunndumpen:

java.lang.OutOfMemoryError: Forespurt arraystørrelse overskrider VM-grense Dumping heap til java_pid12587.hprof ... Unntak i tråd "main" Heap dump-fil opprettet [4744371 byte på 0,029 sek] java.lang.OutOfMemoryError: Forespurt arraystørrelse overskrider VM-grense på com.baeldung.heapdump.App.main (App.java:7)

I eksemplet ovenfor ble det skrevet til java_pid12587.hprof fil.

Som vi kan se, er dette alternativet veldig nyttig og det er ingen overhead når du kjører et program med dette alternativet. Derfor anbefales det sterkt å bruke dette alternativet alltid, spesielt i produksjon.

Endelig, dette alternativet kan også spesifiseres ved kjøretid ved å bruke HotSpotDiagnostic MBean. For å gjøre dette kan vi bruke JConsole og stille inn HeapDumpOnOutOfMemoryError VM-alternativ til ekte:

Vi kan finne mer informasjon om MBeans og JMX i denne artikkelen.

4. JMX

Den siste tilnærmingen som vi vil dekke i denne artikkelen, bruker JMX. Vi bruker HotSpotDiagnostic MBean som vi kort introduserte i forrige avsnitt. Denne MBean gir en dumpHeap metode som godtar to parametere:

  • output-fil: banen til filen for dumpen. Filen skal ha hprof-utvidelsen
  • bo: hvis satt til sant, dumpes bare de aktive objektene i minnet, som vi har sett med jmap før

I de neste avsnittene viser vi to forskjellige måter å påkalle denne metoden for å fange en haugdump.

4.1. JConsole

Den enkleste måten å bruke HotSpotDiagnostic MBean er ved å bruke en JMX-klient som JConsole.

Hvis vi åpner JConsole og koble til en pågående Java-prosess, vi kan navigere til MBaner fanen og finn HotSpotDiagnostic under com.sun.management. I operasjoner kan vi finne dumpHeap metoden som vi har beskrevet før:

Som vist trenger vi bare å introdusere parametrene output-fil og bo inn i det p0 og p1 tekstfelt for å utføre dumpHeap operasjon.

4.2. Programmatisk måte

Den andre måten å bruke HotSpotDiagnostic MBean er ved å påkalle den programmatisk fra Java-kode.

For å gjøre det må vi først få en MBeanServer eksempel for å få et MBean som er registrert i applikasjonen. Etter det, vi trenger rett og slett å få en forekomst av en HotSpotDiagnosticMXBean og kaller det dumpHeap metode.

La oss se det i kode:

public static void dumpHeap (String filePath, boolean live) kaster IOException {MBeanServer server = ManagementFactory.getPlatformMBeanServer (); HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy (server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); mxBean.dumpHeap (filePath, live); }

Legg merke til at en hprof-fil ikke kan overskrives. Derfor bør vi ta hensyn til dette når vi oppretter et program som skriver ut dyppedumper. Hvis vi ikke gjør det, får vi et unntak:

Unntak i tråden "hoved" java.io.IO Unntak: Filen eksisterer på sun.management.HotSpotDiagnostic.dumpHeap0 (Native Method) på sun.management.HotSpotDiagnostic.dumpHeap (HotSpotDiagnostic.java:60)

5. Konklusjon

I denne opplæringen har vi vist flere måter å fange en heap dump i Java.

Som en tommelfingerregel bør vi huske å bruke HeapDumpOnOutOfMemoryError alternativet alltid når du kjører Java-applikasjoner. For andre formål kan ethvert av de andre verktøyene brukes perfekt så lenge vi husker den ikke-støttede statusen til jmap.

Som alltid er hele kildekoden til eksemplene tilgjengelig på GitHub.


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