Verschillende manieren om Java-heapdumps vast te leggen

1. Inleiding

In dit artikel laten we verschillende manieren zien om een ​​heap-dump in Java vast te leggen.

Een heap dump is een momentopname van alle objecten die zich op een bepaald moment in het geheugen van de JVM bevinden. Ze zijn erg handig om problemen met geheugenlekken op te lossen en het geheugengebruik in Java-toepassingen te optimaliseren.

Heap-dumps worden meestal opgeslagen in hprof-bestanden in binair formaat. We kunnen deze bestanden openen en analyseren met tools zoals jhat of JVisualVM. Ook voor Eclipse-gebruikers is het heel gebruikelijk om MAT te gebruiken.

In de volgende secties zullen we meerdere tools en benaderingen doorlopen om een ​​heap-dump te genereren en we zullen de belangrijkste verschillen tussen beide laten zien.

2. JDK-hulpprogramma's

De JDK wordt geleverd met verschillende tools om heap-dumps op verschillende manieren vast te leggen. Al deze tools bevinden zich onder het bak map in de JDK-homedirectory. Daarom kunnen we ze vanaf de opdrachtregel starten, zolang deze map in het systeempad is opgenomen.

In de volgende secties laten we zien hoe u deze tools kunt gebruiken om heap-dumps vast te leggen.

2.1. jmap

jmap is een tool om statistieken over geheugen in een draaiende JVM af te drukken. We kunnen het gebruiken voor lokale of externe processen.

Om een ​​heap-dump vast te leggen met jmap, moeten we de dump keuze:

jmap -dump: [live], formaat = b, bestand = 

Naast die optie moeten we verschillende parameters specificeren:

  • leven: indien ingesteld, worden alleen objecten afgedrukt die actieve referenties hebben en worden de objecten verwijderd die gereed zijn om te worden opgehaald. Deze parameter is optioneel
  • format = b: specificeert dat het dumpbestand in binair formaat zal zijn. Indien niet ingesteld, is het resultaat hetzelfde
  • het dossier: het bestand waarnaar de dump zal worden geschreven
  • pid: id van het Java-proces

Een voorbeeld zou als volgt zijn:

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

Onthoud dat we het pid van een Java-proces met behulp van de jps opdracht.

Houd daar rekening meejmap is in de JDK geïntroduceerd als een experimentele tool en wordt niet ondersteund. Daarom kan het in sommige gevallen de voorkeur hebben om in plaats daarvan andere tools te gebruiken.

2.2. jcmd

jcmd is een zeer complete tool die werkt door opdrachtverzoeken naar de JVM te sturen. We moeten het gebruiken op dezelfde machine waarop het Java-proces wordt uitgevoerd.

Een van de vele opdrachten is de GC.heap_dump. We kunnen het gebruiken om een ​​heap-dump te krijgen door de pid van het proces en het outputbestandspad:

jcmd GC.heap_dump 

We kunnen het uitvoeren met dezelfde parameters die we eerder hebben gebruikt:

jcmd 12587 GC.heap_dump /tmp/dump.hprof

Net als bij jmap is de gegenereerde dump in binair formaat.

2.3. JVisualVM

JVisualVM is een tool met een grafische gebruikersinterface waarmee we Java-applicaties kunnen controleren, problemen oplossen en profileren. De GUI is eenvoudig maar zeer intuïtief en gemakkelijk te gebruiken.

Een van de vele opties stelt ons in staat om een ​​heap-dump vast te leggen. Als we met de rechtermuisknop op een Java-proces klikken en het "Heap Dump" optie, maakt de tool een heap-dump en opent deze op een nieuw tabblad:

Merk op dat we het pad kunnen vinden van het bestand dat is gemaakt in het "Basis informatie" sectie.

Vanaf JDK 9 is Visual VM niet opgenomen in de Oracle JDK- en Open JDK-distributies. Daarom, als we Java 9 of nieuwere versies gebruiken, kunnen we de JVisualVM ophalen van de Visual VM open source projectsite.

3. Leg automatisch een heapdump vast

Alle tools die we in de vorige secties hebben getoond, zijn bedoeld om heap-dumps op een bepaald moment handmatig vast te leggen. In sommige gevallen willen we een hoopdump krijgen als een java.lang.OutOfMemoryError gebeurt, zodat het ons helpt de fout te onderzoeken.

Voor deze gevallen Java biedt het HeapDumpOnOutOfMemoryError opdrachtregeloptie die een heap-dump genereert wanneer een java.lang.OutOfMemoryError wordt gegooid:

java -XX: + HeapDumpOnOutOfMemoryError

Standaard slaat het de dump op in een java_pid.hprof bestand in de map waarin we de applicatie uitvoeren. Als we een ander bestand of map willen specificeren, kunnen we dit in de HeapDumpPath keuze:

java -XX: + HeapDumpOnOutOfMemoryError -XX: HeapDumpPath =

Wanneer onze applicatie met deze optie onvoldoende geheugen heeft, kunnen we in de logboeken het aangemaakte bestand zien dat de heap-dump bevat:

java.lang.OutOfMemoryError: Gevraagde array-grootte overschrijdt VM-limiet Dump-heap naar java_pid12587.hprof ... Uitzondering in thread "main" Heap-dumpbestand gemaakt [4744371 bytes in 0,029 seconden] java.lang.OutOfMemoryError: Gevraagde array-grootte overschrijdt VM-limiet op com.baeldung.heapdump.App.main (App.java:7)

In het bovenstaande voorbeeld is het geschreven naar het java_pid12587.hprof het dossier.

Zoals we kunnen zien, is deze optie erg handig en er is geen overhead bij het draaien van een applicatie met deze optie. Daarom wordt het ten zeerste aanbevolen om deze optie altijd te gebruiken, vooral in productie.

Tenslotte, deze optie kan ook tijdens runtime worden gespecificeerd door de HotSpotDiagnostic MBean. Om dit te doen, kunnen we JConsole gebruiken en de HeapDumpOnOutOfMemoryError VM-optie naar waar:

We kunnen meer informatie vinden over MBeans en JMX in dit artikel.

4. JMX

De laatste benadering die we in dit artikel zullen behandelen, is het gebruik van JMX. We gebruiken de HotSpotDiagnostic MBean die we in de vorige paragraaf kort hebben geïntroduceerd. Deze MBean biedt een dumpHeap methode die 2 parameters accepteert:

  • outputFile: het pad van het bestand voor de dump. Het bestand moet de extensie hprof hebben
  • leven: indien ingesteld op true, worden alleen de actieve objecten in het geheugen gedumpt, zoals we eerder hebben gezien met jmap

In de volgende secties laten we twee verschillende manieren zien om deze methode aan te roepen om een ​​heap-dump vast te leggen.

4.1. JConsole

De gemakkelijkste manier om het HotSpotDiagnostic MBean is door een JMX-client zoals JConsole te gebruiken.

Als we openen JConsole en maak verbinding met een actief Java-proces, we kunnen naar het MBeans tab en zoek het HotSpotDiagnostic onder com.sun.management. In operaties kunnen we de dumpHeap methode die we eerder hebben beschreven:

Zoals getoond, hoeven we alleen de parameters in te voeren outputFile en leven in de p0 en p1 tekstvelden om de dumpHeap operatie.

4.2. Programmatische manier

De andere manier om de HotSpotDiagnostic MBean is door het programmatisch aan te roepen vanuit Java-code.

Om dit te doen, hebben we eerst een MBeanServer bijvoorbeeld om een ​​MBean te krijgen die in de applicatie is geregistreerd. Daarna, we hebben gewoon een instantie nodig van een HotSpotDiagnosticMXBean en bel het dumpHeap methode.

Laten we het in code bekijken:

openbare statische ongeldige dumpHeap (String filePath, boolean live) gooit IOException {MBeanServer server = ManagementFactory.getPlatformMBeanServer (); HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy (server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); mxBean.dumpHeap (filePath, live); }

Merk op dat een hprof-bestand niet kan worden overschreven. Daarom moeten we hier rekening mee houden bij het maken van een applicatie die heap-dumps afdrukt. Als we dit niet doen, krijgen we een uitzondering:

Uitzondering in thread "main" java.io.IOException: bestand bestaat op sun.management.HotSpotDiagnostic.dumpHeap0 (native methode) op sun.management.HotSpotDiagnostic.dumpHeap (HotSpotDiagnostic.java:60)

5. Conclusie

In deze zelfstudie hebben we meerdere manieren getoond om een ​​heap-dump in Java vast te leggen.

Als vuistregel moeten we niet vergeten de HeapDumpOnOutOfMemoryError optie altijd bij het uitvoeren van Java-applicaties. Voor andere doeleinden kan elk van de andere tools perfect worden gebruikt, zolang we de niet-ondersteunde status van jmap in gedachten houden.

Zoals altijd is de volledige broncode van de voorbeelden beschikbaar op GitHub.