Erfassen eines Java-Thread-Dumps

1. Übersicht

In diesem Tutorial werden verschiedene Möglichkeiten zum Erfassen des Thread-Dumps einer Java-Anwendung erläutert.

Ein Thread-Dump ist eine Momentaufnahme des Status aller Threads eines Java-Prozesses . Der Status jedes Threads wird mit einer Stapelverfolgung angezeigt, die den Inhalt des Stapels eines Threads anzeigt. Ein Thread-Dump ist nützlich für die Diagnose von Problemen, da er die Aktivität des Threads anzeigt. Thread-Dumps werden im Klartext geschrieben, sodass wir ihren Inhalt in einer Datei speichern und später in einem Texteditor anzeigen können .

In den nächsten Abschnitten werden verschiedene Tools und Ansätze zum Generieren eines Thread-Dumps beschrieben.

2. Verwenden von JDK-Dienstprogrammen

Das JDK bietet mehrere Dienstprogramme, mit denen der Thread-Dump einer Java-Anwendung erfasst werden kann. Alle Dienstprogramme befinden sich im Ordner bin im JDK-Ausgangsverzeichnis . Daher können wir diese Dienstprogramme über die Befehlszeile ausführen, solange sich dieses Verzeichnis in unserem Systempfad befindet.

2.1. jstack

jstack ist ein Befehlszeilen-JDK-Dienstprogramm, mit dem wir einen Thread-Dump erfassen können. Es nimmt die PID eines Prozesses und zeigt den Thread-Dump in der Konsole an. Alternativ können wir die Ausgabe in eine Datei umleiten.

Werfen wir einen Blick auf die grundlegende Befehlssyntax zum Erfassen eines Thread-Dumps mit jstack:

jstack [-F] [-l] [-m] 

Alle Flags sind optional. Mal sehen, was sie bedeuten:

  • -F Option erzwingt einen Thread Dump; Praktisch zu verwenden, wenn jstack pid nicht reagiert (der Prozess hängt)
  • Die Option -l weist das Dienstprogramm an, im Heap und in den Sperren nach eigenen Synchronisierern zu suchen
  • Die Option -m druckt zusätzlich zu den Java-Stapelrahmen native Stapelrahmen (C & C ++)

Lassen Sie uns dieses Wissen nutzen, indem wir einen Thread-Dump erfassen und das Ergebnis in eine Datei umleiten:

jstack 17264 > /tmp/threaddump.txt

Denken Sie daran , dass wir leicht die bekommen kann pid eines Java - Prozess unter Verwendung des JPS - Befehl.

2.2. Java Mission Control

Java Mission Control (JMC) ist ein GUI-Tool, das Daten aus Java-Anwendungen sammelt und analysiert. Nach dem Start von JMC wird die Liste der Java-Prozesse angezeigt, die auf einem lokalen Computer ausgeführt werden. Wir können auch über JMC eine Verbindung zu Remote-Java-Prozessen herstellen.

Wir können mit der rechten Maustaste auf den Vorgang klicken und auf die Option „ Flugaufzeichnung starten “ klicken . Danach werden auf der Registerkarte Threads die Thread-Dumps angezeigt:

2.3. jvisualvm

jvisualvm ist ein Tool mit einer grafischen Benutzeroberfläche, mit der wir Java-Anwendungen überwachen, Fehler beheben und Profile erstellen können . Die GUI ist einfach, aber sehr intuitiv und einfach zu bedienen.

Eine der vielen Optionen ermöglicht es uns, einen Thread-Dump zu erfassen. Wenn wir mit der rechten Maustaste auf einen Java-Prozess klicken und die Option "Thread-Dump" auswählen , erstellt das Tool einen Thread-Dump und öffnet ihn in einer neuen Registerkarte:

Ab JDK 9 ist Visual VM nicht in den Distributionen Oracle JDK und Open JDK enthalten. Wenn wir Java 9 oder neuere Versionen verwenden, können wir die JVisualVM daher von der Open Source-Projektsite von Visual VM abrufen.

2.4. jcmd

jcmd ist ein Tool, das Befehlsanforderungen an die JVM sendet. Obwohl es leistungsstark ist, enthält es keine Remote-Funktionen - wir müssen es auf demselben Computer verwenden, auf dem der Java-Prozess ausgeführt wird.

Einer der vielen Befehle ist Thread.print . Wir können es verwenden, um einen Thread-Dump zu erhalten, indem wir einfach die PID des Prozesses angeben :

jcmd 17264 Thread.print

2.5. jconsole

Mit jconsole können wir die Stapelverfolgung jedes Threads überprüfen. Wenn wir jconsole öffnen und eine Verbindung zu einem laufenden Java-Prozess herstellen, können wir zur Registerkarte Threads navigieren und den Stack-Trace jedes Threads finden :

2.6. Zusammenfassung

Wie sich herausstellt, gibt es viele Möglichkeiten, einen Thread-Dump mithilfe von JDK-Dienstprogrammen zu erfassen. Nehmen wir uns einen Moment Zeit, um über die einzelnen Vor- und Nachteile nachzudenken:

  • jstack : Bietet die schnellste und einfachste Möglichkeit, einen Thread-Dump zu erfassen. Ab Java 8 stehen jedoch bessere Alternativen zur Verfügung
  • jmc : Erweitertes JDK-Profilierungs- und Diagnosetool. Es minimiert den Leistungsaufwand, der normalerweise bei Profiling-Tools auftritt
  • jvisualvm : Leichtes und Open-Source-Profiling-Tool mit einer hervorragenden GUI-Konsole
  • jcmd : extrem leistungsfähig und empfohlen für Java 8 und höher. Ein einziges Tool, das vielen Zwecken dient: Erfassen von Thread-Dumps ( jstack ), Heap-Dumps ( jmap ), Systemeigenschaften und Befehlszeilenargumenten ( jinfo )
  • jconsole : Lassen Sie uns die Trace-Informationen zum Thread-Stack überprüfen

3. Über die Befehlszeile

In enterprise application servers, only the JRE is installed for security reasons. Thus, we can not use the above-mentioned utilities as they are part of JDK. However, there are various command-line alternatives that let us capture thread dumps easily.

3.1. kill -3 Command (Linux/Unix)

The easiest way to capture a thread dump in Unix-like systems is through the kill command, which we can use to send a signal to a process using the kill() system call. In this use case, we'll send it the -3 signal.

Using our same pid from earlier examples, let's take a look at how to use kill to capture a thread dump:

kill -3 17264

This way the signal-receiving Java process will print the thread dump on the standard output.

If we run the Java process with the following combination of tuning flags, then it will also redirect the thread dump to the given file:

-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=~/jvm.log

Now if we send the -3 signal, in addition to the standard output, the dump will be available at ~/jvm.log file.

3.2. Ctrl + Break (Windows)

In Windows operating systems, we can capture a thread dump using the CTRL and Break key combination. To take a thread dump, navigate to the console used to launch the Java application and press CTRL and Break keys together.

It's worth noting that, on some keyboards, the Break key is not available. Therefore, in such cases, a thread dump can be captured using CTRL, SHIFT, and Pause keys together.

Both of these commands print the thread dump to the console.

4. Programmatically Using ThreadMxBean

The last approach we will discuss in the article is using JMX. We'll use ThreadMxBean to capture the thread dump. Let's see it in code:

private static String threadDump(boolean lockedMonitors, boolean lockedSynchronizers) { StringBuffer threadDump = new StringBuffer(System.lineSeparator()); ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); for(ThreadInfo threadInfo : threadMXBean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) { threadDump.append(threadInfo.toString()); } return threadDump.toString(); }

In the above program, we are performing several steps:

  1. At first, an empty StringBuffer is initialized to hold the stack information of each thread.
  2. We then use the ManagementFactory class to get the instance of ThreadMxBean. A ManagementFactory is a factory class for getting managed beans for the Java platform. In addition, a ThreadMxBean is the management interface for the thread system of the JVM.
  3. Setting lockedMonitors and lockedSynchronizers values to true indicates to capture the ownable synchronizers and all locked monitors in the thread dump.

5. Conclusion

In this article, we've shown multiple ways to capture a thread dump.

At first, we discussed various JDK Utilities and then the command-line alternatives. In the last section, we concluded with the programmatic approach using JMX.

Wie immer ist der vollständige Quellcode des Beispiels auf GitHub verfügbar.