Was ist Thread Dump und wie werden sie analysiert?

Lassen Sie uns über den Thread-Dump sprechen und wie man ihn analysiert.
Wir werden auch diskutieren, wie es hilft, die Probleme und einige der Analysegeräte, die Sie verwenden können, genau zu bestimmen.
Was ist Thread?
A process ist ein Computerprogramm, das in den Speicher des Computers geladen wird und gerade ausgeführt wird. Es kann von a ausgeführt werden processoder oder ein Satz von processors. A process wird im Speicher mit wichtigen Informationen wie Variablenspeichern, Dateihandles, Programmzähler, Registern und Signalen usw. beschrieben.
A process kann aus vielen leichten bestehen processEs heißt Themen. Dies trägt dazu bei, Parallelität zu erreichen, wobei a process ist in mehrere Threads unterteilt. Dies führt zu einer besseren Leistung. Alle Threads innerhalb eines process teilen sich den gleichen Speicherplatz und sind voneinander abhängig.
Thread-Dumps
Wenn das process ausgeführt wird, können wir den aktuellen st erkennenate der Ausführung der Threads in der process Verwenden von Thread-Dumps. Ein Thread-Dump enthält eine Momentaufnahme aller Threads, die zu einem bestimmten Zeitpunkt während der Ausführung eines Programms aktiv sind. Es enthält alle relevanten Informationen zum Thread und seinem aktuellen Threadate.
Eine moderne Anwendung umfasst heute mehrere Threads. Jeder Thread benötigt bestimmte Ressourcen und führt bestimmte Aktivitäten aus related zum process. Dies kann die Leistung einer Anwendung steigern, da Threads verfügbare CPU-Kerne nutzen können.
Aber es gibt Kompromisse, z. B. kann es vorkommen, dass mehrere Threads nicht koordiniert werdenate gut miteinander und es kann zu einer Sackgasse kommenrise. Wenn also etwas schief geht, können wir Thread-Dumps verwenden, um dies zu beheben inspect die state unserer Threads.
Thread-Dump in Java
Ein JVM-Thread-Dump ist eine Auflistung der state aller Threads, die Teil der sind process zu diesem bestimmten Zeitpunkt. Es enthält Informationen über den Stack des Threads, dargestellt als Stack-Trace. Da es im Klartext geschrieben ist, kann der Inhalt gespeichert werden revansehen later. Die Analyse von Thread-Dumps kann hilfreich sein
- Optimierung der JVM-Leistung
- Optimierung der Anwendungsleistung
- Diagnose von Problemen, z. B. Deadlock, Thread-Konflikt usw.
Generierung von Thread-Dumps
Es gibt viele Möglichkeiten zur Generierungate Thread-Dumps. Nachfolgend finden Sie einige JVM-basierte Tools, die über die Befehlszeile/das Terminal (CLI-Tools) oder ausgeführt werden können /Behälter Verzeichnis (GUI-Tools) des Installationsordners von Java.
Lassen Sie uns sie erkunden.
# 1. jStack
Der einfachste Weg zum Generierenate Ein Thread-Dump erfolgt mithilfe von jStack. jStack wird mit JVM geliefert und kann über die Befehlszeile verwendet werden. Hier benötigen wir die PID des process für die wir generieren wollenate der Thread-Dump. Um PID zu erhalten, können wir verwenden jps Befehl wie unten gezeigt.
jps -l
jps
listet alle Java auf process Ausweise.
On Windows
C:\Program Files\Java\jdk1.8.0_171\bin>jps -l
47172 portal
6120 sun.tools.jps.Jps
C:\Program Files\Java\jdk1.8.0_171\bin>
Unter Linux
[geekfkare@localhost ~]# jps -l
1088 /opt/keycloak/jboss-modules.jar
26680 /var/lib/jenkins/workspace/kyc/kyc/target/kyc-1.0.jar
7193 jdk.jcmd/sun.tools.jps.Jps
2058 /usr/share/jenkins/jenkins.war
11933 /var/lib/jenkins/workspace/admin-portal/target/portal-1.0.jar
[geekfkare@localhost ~]#
Wie wir hier sehen können, erhalten wir eine Liste aller laufenden Java processes. Es enthält die lokale VM-ID für das laufende Java process und der Name der Anwendung in den Spalten eins und zwei. Nun zum Generierenate Den Thread-Dump verwenden wir jStack programmieren mit Es Flagge welche Createsa lange aufgelistete Ausgabe des Dumps. Wir können die Ausgabe auch an eine Textdatei unserer Wahl weiterleiten.
jstack -l 26680<br>
[geekfkare@localhost ~]# jstack -l 26680
2020-06-27 06:04:53
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.221-b11 mixed mode):
"Attach Listener" #16287 daemon prio=9 os_prio=0 tid=0x00007f0814001800 nid=0x4ff2 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"logback-8" #2316 daemon prio=5 os_prio=0 tid=0x00007f07e0033000 nid=0x4792 waiting on condition [0x00007f07baff8000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006ca9a1fc0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"logback-7" #2315 daemon prio=5 os_prio=0 tid=0x00007f07e0251800 nid=0x4791 waiting on condition [0x00007f07bb0f9000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006ca9a1fc0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
# 2. jvisualvm
Jvisualvm ist ein GUI-Tool, das uns bei der Fehlerbehebung hilft, monitor und profile Java-Anwendungen. Es wird außerdem mit JVM geliefert und kann von dort aus gestartet werden /Behälter Verzeichnis unserer Java-Installation. Es ist sehr intuitiv und einfach zu bedienen. Neben anderen Optionen ermöglicht es uns auch, Thread-Dumps für einen bestimmten Thread zu erfassen process.
Um den Thread-Dump für einen bestimmten Thread anzuzeigen process, können wir mit der rechten Maustaste auf das Programm klicken und auswählen Thread-Dump in dem Kontextmenü.

# 3. jcmd
JCMD ist ein Befehlszeilenprogramm, das im Lieferumfang des JDK enthalten ist und zum Senden von Diagnosebefehlsanforderungen an die JVM verwendet wird.
Es funktioniert jedoch nur auf dem lokalen Computer, auf dem die Java-Anwendung ausgeführt wird. Es kann verwendet werden, um Java-Flugaufzeichnungen zu steuern, JVM- und Java-Anwendungen zu diagnostizieren und Fehler zu beheben. Wir können die verwenden Thread.print
Befehl von jcmd, um eine Liste der Thread-Dumps für einen bestimmten Thread abzurufen process durch die PID vorgegeben.
Nachfolgend finden Sie ein Beispiel für die Verwendung jcmd
.
jcmd 28036 Thread.print
C:\Program Files\Java\jdk1.8.0_171\bin>jcmd 28036 Thread.print
28036:
2020-06-27 21:20:02
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.171-b11 mixed mode):
"Bundle File Closer" #14 daemon prio=5 os_prio=0 tid=0x0000000021d1c000 nid=0x1d4c in Object.wait() [0x00000000244ef000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.getNextEvent(EventManager.java:403)
- locked <0x000000076f380a88> (a org.eclipse.osgi.framework.eventmgr.EventManager$EventThread)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:339)
"Active Thread: Equinox Container: 0b6cc851-96cd-46de-a92b-253c7f7671b9" #12 prio=5 os_prio=0 tid=0x0000000022e61800 nid=0xbff4 waiting on condition [0x00000000243ee000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076f388188> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x0000000021a7b000 nid=0x2184 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread3" #9 daemon prio=9 os_prio=2 tid=0x00000000219f5000 nid=0x1300 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x00000000219e0000 nid=0x48f4 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x00000000219df000 nid=0xb314 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x00000000219db800 nid=0x2260 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000000219d9000 nid=0x125c waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00000000219d8000 nid=0x834 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001faf3000 nid=0x36c0 in Object.wait() [0x0000000021eae000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076f390180> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
- locked <0x000000076f390180> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000005806000 nid=0x13c0 in Object.wait() [0x00000000219af000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076f398178> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Unknown Source)
at java.lang.ref.Reference.tryHandlePending(Unknown Source)
- locked <0x000000076f398178> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
"main" #1 prio=5 os_prio=0 tid=0x000000000570e800 nid=0xbf8 runnable [0x0000000000fec000]
java.lang.Thread.State: RUNNABLE
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(Unknown Source)
at java.util.zip.ZipFile.<init>(Unknown Source)
at java.util.zip.ZipFile.<init>(Unknown Source)
at org.eclipse.osgi.framework.util.SecureAction.getZipFile(SecureAction.java:307)
at org.eclipse.osgi.storage.bundlefile.ZipBundleFile.getZipFile(ZipBundleFile.java:136)
at org.eclipse.osgi.storage.bundlefile.ZipBundleFile.lockOpen(ZipBundleFile.java:83)
at org.eclipse.osgi.storage.bundlefile.ZipBundleFile.getEntry(ZipBundleFile.java:290)
at org.eclipse.equinox.weaving.hooks.WeavingBundleFile.getEntry(WeavingBundleFile.java:65)
at org.eclipse.osgi.storage.bundlefile.BundleFileWrapper.getEntry(BundleFileWrapper.java:55)
at org.eclipse.osgi.storage.BundleInfo$Generation.getRawHeaders(BundleInfo.java:130)
- locked <0x000000076f85e348> (a java.lang.Object)
at org.eclipse.osgi.storage.BundleInfo$CachedManifest.get(BundleInfo.java:599)
at org.eclipse.osgi.storage.BundleInfo$CachedManifest.get(BundleInfo.java:1)
at org.eclipse.equinox.weaving.hooks.SupplementerRegistry.addSupplementer(SupplementerRegistry.java:172)
at org.eclipse.equinox.weaving.hooks.WeavingHook.initialize(WeavingHook.java:138)
at org.eclipse.equinox.weaving.hooks.WeavingHook.start(WeavingHook.java:208)
at org.eclipse.osgi.storage.FrameworkExtensionInstaller.startActivator(FrameworkExtensionInstaller.java:261)
at org.eclipse.osgi.storage.FrameworkExtensionInstaller.startExtensionActivators(FrameworkExtensionInstaller.java:198)
at org.eclipse.osgi.internal.framework.SystemBundleActivator.start(SystemBundleActivator.java:112)
at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:815)
at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:808)
at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:765)
at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1005)
at org.eclipse.osgi.internal.framework.EquinoxBundle$SystemBundle$EquinoxSystemModule.initWorker(EquinoxBundle.java:190)
at org.eclipse.osgi.container.SystemModule.init(SystemModule.java:99)
at org.eclipse.osgi.internal.framework.EquinoxBundle$SystemBundle.init(EquinoxBundle.java:272)
at org.eclipse.osgi.internal.framework.EquinoxBundle$SystemBundle.init(EquinoxBundle.java:257)
at org.eclipse.osgi.launch.Equinox.init(Equinox.java:171)
at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:316)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:251)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:661)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:597)
at org.eclipse.equinox.launcher.Main.run(Main.java:1476)
"VM Thread" os_prio=2 tid=0x000000001fae8800 nid=0x32cc runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000005727800 nid=0x3264 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000005729000 nid=0xbdf4 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000000000572a800 nid=0xae6c runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000572d000 nid=0x588 runnable
"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x000000000572f000 nid=0xac0 runnable
"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000005730800 nid=0x380 runnable
"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000005733800 nid=0x216c runnable
"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000005734800 nid=0xb930 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x0000000021a8d000 nid=0x2dcc waiting on condition
JNI global references: 14
C:\Program Files\Java\jdk1.8.0_171\bin>
# 4. JMC
JMC steht für Java-Missionskontrolle. Es ist ein Open-Source-GUI-Tool, das im Lieferumfang von JDK enthalten ist und zum Sammeln und Analysieren von Java-Anwendungsdaten verwendet wird.
Es kann von der gestartet werden /Behälter Ordner unserer Java-Installation. Java-Administratoren und -Entwickler verwenden das Tool, um detaillierte Informationen auf niedriger Ebene über das Verhalten der JVM und der Anwendung zu sammeln. Es ermöglicht eine detaillierte und effiziente Analyse der von Java gesammelten Daten Flug Rekorder.
Beim Start jmc
, wir können die Liste von Java sehen process welches auf dem lokalen Rechner läuft. Auch eine Remote-Verbindung ist möglich. Auf ein bestimmtes process, wir können mit der rechten Maustaste klicken und auswählen Starten Sie die Flugaufzeichnung und überprüfen Sie dann die Thread-Dumps in der Themen Tab.

# 5. jconsole
jconsole ist ein Java Management Extension-Tool, das für verwendet wird Beschwerde Management und monitoring.
Es gibt auch eine Reihe vordefinierter Operationen für den JMX-Agenten, die der Benutzer ausführen kann. Es ermöglicht dem Benutzer das Erkennen und Analysieren der Stapelverfolgung eines Live-Programms. Es kann von der gestartet werden /Behälter Ordner unserer Java-Installation.
Verwendung der jconsole GUI-Tool können wir inspect Der Stack-Trace jedes Threads, wenn wir ihn mit einem laufenden Java verbinden process. Dann können wir auf der Registerkarte „Thread“ die Namen aller laufenden Threads sehen. Um einen Deadlock zu erkennen, können wir auf klicken Deadlock erkennen unten rechts im window. Wenn ein Deadlock erkannt wird, wird dieser in einer neuen Registerkarte angezeigtwise a Kein Deadlock erkannt wird Angezeigt werden.

# 6. ThreadMxBean
ThreadMXBean ist die Schnittstelle für die Verwaltung des Thread-Systems der virtuellen Java-Maschine, die zum Paket java.lang.Management gehört. Es wird hauptsächlich verwendet, um die Threads zu erkennen, die in eine Deadlock-Situation eingetreten sind, und um Details darüber abzurufen.
Wir können die ThreadMxBean-Schnittstelle für die Programmierung verwendenally Erfassen Sie den Thread-Dump. getThreadMXBean()
Methode von ManagementFactory
wird verwendet, um eine Instanz von zu erhalten ThreadMXBean
Schnittstelle. Es gibt die Anzahl der Daemon- und Nicht-Daemon-Live-Threads zurück. ManagementFactory ist eine Factory-Klasse zum Abrufen der verwalteten Beans für Java platForm.
private static String getThreadDump (boolean lockMonitors, boolean lockSynchronizers) {
StringBuffer threadDump = new StringBuffer (System.lineSeparator ());
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean ();
for (ThreadInfo threadInfo : threadMXBean.dumpAllThreads (lockMonitors, lockSynchronizers)) {
threadDump.append (threadInfo.toString ());
}
return threadDump.toString ();
}
Manuelle Analyse von Thread-Dumps
Die Analyse von Thread-Dumps kann bei der Lokalisierung von Problemen in Multithreading sehr nützlich sein processes. Es können Probleme wie Deadlocks, Sperrenkonflikte und übermäßige CPU-Auslastung durch einzelne Thread-Dumps auftreten resolved durch Visualisierung des states einzelner Thread-Dumps.
Der maximale Durchsatz der Anwendung kann erreicht werden, indem der Status jedes Threads nach der Analyse des Thread-Dumps korrigiert wird.
Zum Beispiel, sagen wir mal, a process Wenn ein Thread viel CPU verbraucht, können wir herausfinden, ob ein Thread die CPU am meisten beansprucht. Wenn es einen solchen Thread gibt, wandeln wir seine LWP-Nummer in eine Hexadezimalzahl um. Dann können wir aus dem Thread-Dump den Thread finden, dessen Nid gleich p istrevMöglichst erhaltene Hexadezimalzahl. Mithilfe des Stack-Trace des Threads können wir das Problem lokalisieren. Finden wir es heraus process Geben Sie mithilfe des folgenden Befehls die ID des Threads ein.
ps -mo pid,lwp,stime,time,cpu -C java
[geekfkare@localhost ~]# ps -mo pid,lwp,stime,time,cpu -C java
PID LWP STIME TIME %CPU
26680 - Dec07 00:02:02 99.5
- 10039 Dec07 00:00:00 0.1
- 10040 Dec07 00:00:00 95.5
Werfen wir einen Blick auf den folgenden Teil des Thread-Dumps. Um einen Thread-Dump zu erhalten process 26680, verwenden jstack -l 26680
[geekfkare@localhost ~]# jstack -l 26680
2020-06-27 09:01:29
<strong>Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.221-b11 mixed mode):</strong>
"Attach Listener" #16287 daemon prio=9 os_prio=0 tid=0x00007f0814001800 nid=0x4ff2 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
.
.
.
.
.
.
.
"<strong>Reference Handler</strong>" #2 daemon prio=10 os_prio=0 tid=0x00007f085814a000 nid=0x6840 in Object.wait() [0x00007f083b2f1000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000006c790fbd0> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=0 tid=0x00007f0858140800 nid=0x683f runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f0858021000 nid=0x683b runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f0858022800 nid=0x683c runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f0858024800 nid=0x683d runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f0858026000 nid=0x683e runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007f08581a0000 nid=0x6847 waiting on condition
JNI global references: 1553
Nun wollen wir sehen, was wir mit Thread-Dumps untersuchen können. Wenn wir den Thread-Dump beobachten, können wir viele Inhalte sehen, die überwältigend sein können. Wenn wir jedoch Schritt für Schritt vorgehen, kann dies ziemlich einfach zu verstehen sein. Lassen Sie uns die erste Zeile verstehen
2020-06-27 09:01:29
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.221-b11 mixed mode):
Oben wird der Zeitpunkt angezeigt, zu dem der Dump erstellt wurdeated und Informationen über die verwendete JVM. Als nächstes können wir am Ende die Liste der Threads sehen, der erste davon ist unser ReferenceHandler Faden.
Blockierte Threads analysieren
Wenn wir die folgenden Thread-Dump-Protokolle analysieren, können wir feststellen, dass Threads mit erkannt wurden GESPERRT Status, der die Leistung einer Anwendung sehr langsam macht. Also, wenn wir das finden können GESPERRT Threads, wir können es versuchen extract die Threads related zu den Sperren, die die Threads zu erhalten versuchen. Die Analyse des Stack-Trace des Threads, der aktuell die Sperre hält, kann bei der Lösung des Problems hilfreich sein.
[geekfkare@localhost ~]# jstack -l 26680
.
.
.
.
" DB-Processor-13" daemon prio=5 tid=0x003edf98 nid=0xca waiting for monitor entry [0x000000000825f000]
java.lang.Thread.State: <strong>BLOCKED</strong> (on object monitor)
at beans.ConnectionPool.getConnection(ConnectionPool.java:102)
- waiting to lock <0xe0375410> (a beans.ConnectionPool)
at beans.cus.ServiceCnt.getTodayCount(ServiceCnt.java:111)
at beans.cus.ServiceCnt.insertCount(ServiceCnt.java:43)
"DB-Processor-14" daemon prio=5 tid=0x003edf98 nid=0xca waiting for monitor entry [0x000000000825f020]
java.lang.Thread.State: <strong>BLOCKED</strong> (on object monitor)
at beans.ConnectionPool.getConnection(ConnectionPool.java:102)
- waiting to lock <0xe0375410> (a beans.ConnectionPool)
at beans.cus.ServiceCnt.getTodayCount(ServiceCnt.java:111)
at beans.cus.ServiceCnt.insertCount(ServiceCnt.java:43)
.
.
.
.
Deadlock-Thread analysieren
Eine andere sehr häufig verwendete Anwendung von Thread-Dumps ist die Erkennung von Deadlocks. Das Erkennen und Lösen von Deadlocks kann viel einfacher sein, wenn wir die Thread-Dumps analysieren.
Ein Deadlock ist eine Situation mit mindestens zwei Threads, in der die Ressource, die ein Thread benötigt, um die Ausführung fortzusetzen, von einem anderen Thread gesperrt wird und gleichzeitig die vom zweiten Thread benötigte Ressource vom ersten Thread gesperrt wird.
Daher kann keiner der Threads die Ausführung fortsetzen. Dies führt zu einer Deadlock-Situation und führt dazu, dass die Anwendung hängen bleibt. Wenn Dreadlocks vorhanden sind, werden im letzten Abschnitt des Thread-Dumps die Informationen zum Deadlock wie folgt ausgedruckt.
"Thread-0":
waiting to lock monitor 0x00000250e4982480 (object 0x00000000894465b0, a java.lang.Object),
which is held by "Thread-1"
"Thread-1":
waiting to lock monitor 0x00000250e4982380 (object 0x00000000894465a0, a java.lang.Object),
which is held by "Thread-0"
.
.
.
"Thread-0":
at DeadlockedProgram$DeadlockedRunnableImplementation.run(DeadlockedProgram.java:34)
- waiting to lock <0x00000000894465b0> (a java.lang.Object)
- locked <0x00000000894465a0> (a java.lang.Object)
at java.lang.Thread.run(java.base@10.0.1/Thread.java:844)
"Thread-1":
at DeadlockedProgram $DeadlockRunnableImplementation.run(DeadlockedProgram.java:34)
- waiting to lock <0x00000000894465a0> (a java.lang.Object)
- locked <0x00000000894465b0> (a java.lang.Object)
at java.lang.Thread.run(java.base@10.0.1/Thread.java:844)
Hier können wir die Deadlock-Informationen in einem für Menschen lesbaren Format sehen.
Abgesehen davon, wenn wir alle oben genannten Teile des Thread-Dumps zusammenfassen, dann ist es stateDies sind die folgenden Informationen.
- Referenzhandler ist der für Menschen lesbare Name des Threads.
- #2 ist die eindeutige ID des Threads.
- Daemon Gibt an, ob der Thread ein Daemon-Thread ist.
- Die numerische Priorität des Threads ist gegeben durch prio= 10.
- Der aktuelle Status des Threads wird mit bezeichnet Warten unter der Bedingung.
- Dann sehen wir die Stapelverfolgung, die die Sperrinformationen enthält.
Thread-Dump-Analysatoren
Neben der manuellen Analyse stehen zahlreiche Tools zur Online- und Offline-Analyse von Thread-Dumps zur Verfügung. Im Folgenden finden Sie einige der aufgeführten Tools, die wir je nach Anforderung verwenden können.
Lassen Sie uns zunächst die Online-Tools untersuchen.
# 1. Schneller Thread
Schneller Thread lernen muss die DevOps Das beliebteste Thread-Dump-Analysetool des Ingenieurs zur Behebung komplexer Produktionsprobleme. Dies ist ein Online-Java-Thread-Dump-Analysator. Wir können den Thread-Dump als Datei hochladen oder den Thread-Dump direkt kopieren und einfügen.
Abhängig von der Größe wird der Thread-Dump analysiert und die im Screenshot gezeigten Informationen angezeigt.

Eigenschaften
- Fehlerbehebung bei JVM-Abstürzen, Verlangsamungen, Speicherlecks, Einfrieren und CPU-Spitzen
- Sofortige Cinch (nicht auf Anbieter warten)
- Intuitives Dashboard
- REST-API-Unterstützung
- Maschinelles lernen
# 2. Spotify-Thread-Dump-Analysator
Der Spotify-Thread-Dump-Analysator ist unter Version 2.0 der Apache-Lizenz lizenziert. Es ist ein Online-Tool und akzeptiert den Thread-Dump als Datei, oder wir können den Thread-Dump direkt kopieren und einfügen. Abhängig von der Größe wird der Thread-Dump analysiert und die im Screenshot gezeigten Informationen angezeigt.

# 3. Jstack review
Jstack.review Analysiert Java-Thread-Dumps aus dem b herausrowsähm. Diese Seite ist nur clientseitig.

# 4. Webseite 24 × 7
Dieser Werkzeug ist eine Voraussetzung für die Erkennung fehlerhafter Threads, die die Leistung der Java Virtual Machine (JVM) beeinträchtigen. Es können Probleme wie Deadlocks, Sperrenkonflikte und übermäßige CPU-Auslastung durch einzelne Thread-Dumps auftreten resolved durch Visualisierung des states einzelner Thread-Dumps.
Der maximale Durchsatz der App kann erreicht werden, indem der Status jedes vom Tool bereitgestellten Threads korrigiert wird.

Lassen Sie uns nun die Offline-Tools untersuchen.
Wenn es um die profiFür uns ist nur das beste Werkzeug gut genug.
# 1. JProfiler
JProfiler ist einer der beliebtesten Thread-Dump-Analysatoren unter Java-Entwickler.. JProfiDie intuitive Benutzeroberfläche von ler hilft Ihnen dabei resolve Erkennen Sie Leistungsengpässe, lokalisieren Sie Speicherlecks und verstehen Sie Threading-Probleme.

JProfiler unterstützt profiling auf Folgendes platFormen:
- Windows
- macOS
- Linux
- FreeBSD
- Solaris
- AIX
- HP-UX
Nachfolgend sind einige Funktionen aufgeführt, die J. auszeichnenProfiler die erste Wahl für profiling unsere Anwendungen auf der JVM.
Eigenschaften
- Unterstützt Datenbank profiling für JDBC, JPA und NoSQL
- Unterstützung für Java enterprise Edition ist ebenfalls erhältlich
- Bietet allgemeine Informationen zu RMI-Anrufen
- Stellar Analyse von Speicherlecks
- Umfangreiche QS-Funktionen
- Die integrated Thread profiler ist eng integrated mit der CPU profiling Ansichten.
- Unterstützung für platFormulare, IDEs und Anwendungsserver.
# 2. IBM TMDA
IBM Thread und Monitor Dump-Analysator für Java (TMDA) ist ein Tool, mit dem Hangs, Deadlocks, Ressourcenkonflikte und Engpässe in Java-Thread-Dumps identifiziert werden können. Es handelt sich um ein IBM Produkt, das TMDA-Tool wird jedoch ohne Garantie oder Support bereitgestellt. Sie versuchen jedoch, das Tool im Laufe der Zeit zu reparieren und zu verbessern.

# 3. ManageEngine
ManageEngine Der Anwendungsmanager kann dabei helfen monitor JVM-Heap- und Nicht-Heap-Speicher. Wir können sogar Schwellenwerte konfigurieren und per E-Mail, SMS usw. benachrichtigt werden und sicherstellen, dass eine Java-Anwendung gut abgestimmt ist.

# 4. DeinKit
DeinKit besteht aus den folgenden Produkten, die als Kit bezeichnet werden.
- Javac Profiler – Voll ausgestattet, geringer Overhead profiler für Java EE und Java SE platFormen.
- DuMonitor - Leistung monitorund profiling von Jenkins, Team City, Gradle, Maven, Ant, JUnit und TestNG.
- .NET Profiler – Einfach zu bedienende Leistung und Speicher profiler für .NET Framework.
Schlussfolgerung
Jetzt wissen Sie, wie nützlich Thread-Dumps in Understanding und Diagnose von Problemen in Multithread-Anwendungen. Mit ordentlich WissenIn Bezug auf die Thread-Dumps - ihre Struktur, die darin enthaltenen Informationen usw. - können wir sie verwenden, um die Ursachen der Probleme schnell zu identifizieren.