Heim  >  Artikel  >  Java  >  Detaillierte JVM-Analyse des Java-Thread-Stacks

Detaillierte JVM-Analyse des Java-Thread-Stacks

高洛峰
高洛峰Original
2017-01-23 10:19:151495Durchsuche

In diesem Artikel werde ich Ihnen beibringen, wie Sie den JVM-Thread-Stack analysieren und anhand der Stack-Informationen die Grundursache des Problems ermitteln. Meiner Meinung nach ist die Thread-Stack-Analysetechnologie eine Technologie, die Java EE-Produktsupportingenieure beherrschen müssen. Die im Thread-Stack gespeicherten Informationen übersteigen in der Regel weit Ihre Vorstellungskraft und wir können diese Informationen bei unserer Arbeit sinnvoll nutzen.

Mein Ziel ist es, das Wissen und die Erfahrung zu teilen, die ich in den letzten zwölf Jahren in der Thread-Analyse gesammelt habe. Dieses Wissen und diese Erfahrung wurden durch eine eingehende Analyse verschiedener JVM-Versionen und JVM-Anbieter verschiedener Anbieter gewonnen. Dabei habe ich auch eine große Anzahl gängiger Problemvorlagen zusammengefasst.

Also, sind Sie bereit? Setzen Sie jetzt ein Lesezeichen für diesen Artikel und ich werde Ihnen in den folgenden Wochen diese Reihe besonderer Artikel präsentieren. Worauf warten Sie noch? Bitte teilen Sie diesen Thread-Analyse-Schulungsplan mit Ihren Kollegen und Freunden.

Hört sich gut an, ich sollte meine Fähigkeiten zur Thread-Stack-Analyse wirklich verbessern ... aber wo fange ich an?

Mein Rat ist, mich durch dieses Thread-Analyse-Schulungsprogramm zu begleiten. Nachfolgend finden Sie die Schulungsinhalte, die wir behandeln werden. Gleichzeitig werde ich Ihnen die tatsächlichen Fälle mitteilen, die ich bearbeitet habe, damit Sie etwas lernen und verstehen können.

1) Überblick und Grundkenntnisse über Thread-Stacks
2) Prinzipien der Thread-Stack-Generierung und verwandte Tools
3) Unterschiede in den Formaten von Thread-Stacks in verschiedenen JVMs (Sun HotSpot, IBM JRE, Oracal JRockit)
4) Einführung und Analysemethode des Thread-Stack-Protokolls
5) Thread-Stack-Analyse und verwandte Technologien
6) Häufige Problemvorlagen (Thread-Race, Deadlock, IO-Aufruf hängen, Garbage Collection/OutOfMemoryError-Probleme, unendlich Schleifen usw.)
7) Beispielanalyse von Thread-Stack-Problemen

Ich hoffe, dass diese Schulungsreihe Ihnen echte Hilfe bringen kann, also achten Sie bitte weiterhin auf wöchentliche Artikelaktualisierungen.

Aber was soll ich tun, wenn ich während des Lernprozesses Fragen habe oder den Inhalt des Artikels nicht verstehen kann?

Keine Sorge, betrachten Sie mich einfach als Ihren Mentor. Bei Fragen zum Thread-Stack können Sie sich an mich wenden (sofern das Problem nicht zu gering ist). Bitte wählen Sie einen der folgenden Wege, um mit mir in Kontakt zu treten:

1) Hinterlassen Sie einen Kommentar direkt unter diesem Artikel (Sie können anonym bleiben, wenn es Ihnen leid tut)
2) Senden Sie Ihren Kommentar Thread-Stack-Daten an das Root Cause Analysis-Forum
3) Senden Sie mir eine E-Mail an @phcharbonneau@hotmail.com

Können Sie mir bei der Analyse der in unseren Produkten aufgetretenen Probleme helfen?

Wenn Sie möchten, können Sie mir natürlich Ihre Stack-Live-Daten per E-Mail oder über das Root Cause Analysis-Forum senden. Der Umgang mit praktischen Problemen ist der beste Weg, Fähigkeiten zu erlernen und zu verbessern.

Ich hoffe wirklich, dass euch allen dieses Training gefällt. Deshalb werde ich mein Bestes tun, um Ihnen hochwertige Materialien zur Verfügung zu stellen und Ihre verschiedenen Fragen zu beantworten.

Bevor ich die Thread-Stack-Analysetechnologie und Problemmuster vorstelle, muss ich Ihnen zunächst die Grundlagen erläutern. Daher werde ich in diesem Beitrag zunächst die grundlegendsten Inhalte behandeln, damit jeder die Interaktion zwischen JVM, Middleware und Java EE-Containern besser verstehen kann.

Java VM-Übersicht

Die Java Virtual Machine ist die Grundlage der Java EE-Plattform. Hier werden Middleware und Anwendungen bereitgestellt und ausgeführt.

JVM stellt die folgenden Dinge für Middleware-Software und Ihre Java/Java EE-Programme bereit:

– (in binärer Form) Java/Java EE-Programmausführungsumgebung
– Einige Programmfunktionen und Tools (IO-Infrastruktur, Datenstrukturen, Thread-Management, Sicherheit, Überwachung usw.)
– Dynamische Speicherzuweisung und -verwaltung mit Garbage Collection

Ihre JVM kann auf vielen Betriebssystemen (Solaris, AIX, Windows usw.) und abhängig von Ihrer physischen Serverkonfiguration können Sie einen bis mehrere JVM-Prozesse auf jedem physischen/virtuellen Server installieren.

JVM und Interaktion zwischen Middleware

Das Folgende Die Abbildung zeigt das High-Level-Interaktionsmodell zwischen JVM, Middleware und Anwendungen.

Detaillierte JVM-Analyse des Java-Thread-Stacks

Die Abbildung zeigt einige einfache und typische Interaktionen zwischen JVM, Middleware und Anwendungssoftware. Wie Sie sehen, erfolgt die Zuweisung von Threads für Standard-Java-EE-Anwendungen zwischen dem Middleware-Kernel und der JVM. (Natürlich gibt es Ausnahmen. Anwendungen können die API direkt aufrufen, um Threads zu erstellen. Dies ist nicht üblich und bei der Verwendung ist besondere Vorsicht geboten.)

Beachten Sie gleichzeitig, dass einige Threads intern erstellt werden Ein typisches Beispiel für die Verwaltung ist der Garbage-Collection-Thread. Dieser Thread wird intern von der JVM verwendet, um eine parallele Garbage-Collection-Verarbeitung durchzuführen.

Da der Großteil der Thread-Zuweisung durch den Java EE-Container erfolgt, ist es wichtig, dass Sie Thread-Stack-Traces verstehen und erkennen und anhand der Thread-Stack-Daten identifizieren können

Aus der Analyseperspektive eines Thread-Dump-Stacks können Sie die Unterschiede zwischen den von der JVM erkannten Thread-Pools verstehen und den Typ der Anfrage identifizieren.

Im letzten Abschnitt erhalten Sie einen Überblick über den JVM-Thread-Stack für HotSop VM sowie über die verschiedenen Threads, auf die Sie stoßen werden. Einzelheiten zum IBM VM-Thread-Stack-Formular finden Sie in Abschnitt 4 Sie.

Bitte beachten Sie, dass Sie ein Thread-Stack-Beispiel für diesen Artikel im Root Cause Analysis Forum erhalten können.

JVM Thread Stack – Was ist das?

Die JVM Thread-Stapel ist eine Momentaufnahme zu einem bestimmten Zeitpunkt, die Ihnen eine vollständige Liste aller Java-Threads liefert, die erstellt wurden.

Jeder entdeckte Java-Thread liefert Ihnen die folgenden Informationen:

– Die Name des Threads; wird häufig von Middleware-Herstellern verwendet, um Threads zu identifizieren. Er enthält normalerweise auch den zugewiesenen Thread-Pool-Namen und -Status (läuft ausgeführt, blockiert usw.) – Thread-Typ und -Priorität, zum Beispiel: daemon prio=3 ** Middleware-Programme erstellen ihre Threads im Allgemeinen in Form von Hintergrund-Daemons, was bedeutet, dass diese Threads im Hintergrund ausgeführt werden und Dienste für ihre Benutzer bereitstellen, zum Beispiel: für Ihre Java EE-Anwendung **

– Java-Thread-ID, zum Beispiel: tid=0x000000011e52a800 ** Dies ist die über java.lang.Thread.getId() erhaltene Java-Thread-ID, die häufig als langes, sich selbst erhöhendes Shaping 1..n** verwendet wird implementiert

– native Thread-ID, zum Beispiel: nid=0x251c**, der Grund für den Schlüssel liegt darin, dass Sie mit der nativen Thread-ID Informationen erhalten können, z. B. aus der Perspektive des Betriebssystems Thread verbraucht die meiste CPU-Zeit in Ihrer JVM. **


– Java-Thread-Status und -Details, zum Beispiel: Warten auf Monitoreintrag [0xfffffffea5afb000] java.lang.Thread .State: BLOCKED (auf Objektmonitor )

** Sie können den Thread-Status und die möglichen Gründe für die aktuelle Blockierung schnell verstehen**


– Dies ist, was Sie bisher vom Thread-Stack aus tun können Daten gefunden in % Informationen.

– Java-Heap-Speicherzerlegung; ab HotSpot VM Version 1.6 können Sie die Speichernutzung von HotSpot am Ende des Thread-Stacks sehen, z. B. Javas Heap-Speicher (YoungGen, OldGen) und PermGen-Speicherplatz. Diese Informationen sind hilfreich bei der Analyse von Problemen, die durch häufige GC verursacht werden. Für eine schnelle Lokalisierung können Sie bekannte Thread-Daten oder -Muster nutzen.


Großer Abbau der Thread-Stack-Informationen
Heap
PSYoungGen   total 466944K, used 178734K [0xffffffff45c00000, 0xffffffff70800000, 0xffffffff70800000)
eden space 233472K, 76% used [0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000)
from space 233472K, 0% used [0xffffffff62400000,0xffffffff62400000,0xffffffff70800000)
to  space 233472K, 0% used [0xffffffff54000000,0xffffffff54000000,0xffffffff62400000)
PSOldGen    total 1400832K, used 1400831K [0xfffffffef0400000, 0xffffffff45c00000, 0xffffffff45c00000)
object space 1400832K, 99% used [0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000)
PSPermGen    total 262144K, used 248475K [0xfffffffed0400000, 0xfffffffee0400000, 0xfffffffef0400000)
object space 262144K, 94% used [0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee0400000)

Um Ihnen ein besseres Verständnis zu ermöglichen, stellen wir Ihnen das folgende Bild zur Verfügung, in dem die Thread-Stack-Informationen auf HotSpot VM dargestellt sind eine detaillierte Zerlegung des Thread-Pools, wie in der folgenden Abbildung dargestellt:

Detaillierte JVM-Analyse des Java-Thread-StacksWie in der obigen Abbildung zu sehen ist, besteht der Thread-Stapel aus mehreren verschiedenen Teilen. Diese Informationen sind alle für die Problemanalyse wichtig, aber verschiedene Teile werden zur Analyse verschiedener Problemmuster verwendet (Problemmuster werden in späteren Artikeln simuliert und demonstriert).

Lassen Sie mich nun durch dieses Analysebeispiel gehen Erklären Sie im Detail die verschiedenen Komponenten der Thread-Stack-Informationen auf HoteSpot:


# Full thread dump标示符

„Vollständiger Thread-Dump“ ist ein weltweit eindeutiges Schlüsselwort, das Sie im Ausgabeprotokoll von finden können Thread-Stack-Informationen der Middleware und der eigenständigen Version von Java (verwenden Sie beispielsweise: kill -3 unter UNIX). Dies ist der Beginn des Thread-Stack-Snapshots.

Vollständiger Thread-Dump Java HotSpot(TM) 64-Bit Server VM (20.0-b11 gemischter Modus):

# Threads in Java EE-Middleware, Drittanbieter- und benutzerdefinierter Anwendungssoftware

Dieser Teil ist der Kernteil des gesamten Thread-Stacks und auch der Teil, der normalerweise die meiste Analysezeit in Anspruch nimmt. Die Anzahl der Threads im Stapel hängt von der von Ihnen verwendeten Middleware, Bibliotheken von Drittanbietern (die möglicherweise unabhängige Threads haben) und Ihrer Anwendung ab (wenn Sie benutzerdefinierte Threads erstellen, ist dies normalerweise keine gute Vorgehensweise).

In unserem Beispiel-Thread-Stack ist WebLogic die Middleware, die wir verwenden. Ab Weblogic 9.2 wird ein selbstverwalteter Thread-Pool verwendet, der eindeutig mit „'weblogic.kernel.Default (self-tuning)“ identifiziert wird



"[STANDBY] ExecuteThread: '414' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon prio=3 tid=0x000000010916a800 nid=0x2613 in Object.wait() [0xfffffffe9edff000]
  java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0xffffffff27d44de0> (a weblogic.work.ExecuteThread)
    at java.lang.Object.wait(Object.java:485)
    at weblogic.work.ExecuteThread.waitForRequest(ExecuteThread.java:160)
    - locked <0xffffffff27d44de0> (a weblogic.work.ExecuteThread)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)

# HotSpot VM-Thread

Dies ist ein interner Thread, der von Hotspot VM verwaltet und zur Durchführung interner nativer Vorgänge verwendet wird. Im Allgemeinen müssen Sie sich darüber keine allzu großen Sorgen machen, es sei denn, Sie stellen eine hohe CPU-Auslastung fest (über zugehörige Thread-Stacks und Prstat- oder native Thread-IDs).



"VM Periodic Task Thread" prio=3 tid=0x0000000101238800 nid=0x19 waiting on condition

# HotSpot-GC-Threads

Bei der Verwendung von HotSpot für parallele GC (heutzutage üblich in Umgebungen mit mehreren physischen Kernen) verwaltet die standardmäßig erstellte HotSpot-VM oder jede JVM einen GC-Thread mit einer bestimmten Identität. Diese GC-Threads ermöglichen der VM, ihre Aufgaben auszuführen regelmäßige GC-Bereinigung parallel, was zu einer Gesamtverkürzung der GC-Zeit führt und gleichzeitig die Kosten für die CPU-Nutzung erhöht.


"GC task thread#0 (ParallelGC)" prio=3 tid=0x0000000100120000 nid=0x3 runnable
"GC task thread#1 (ParallelGC)" prio=3 tid=0x0000000100131000 nid=0x4 runnable
………………………………………………………………………………………………………………………………………………………………

这事非常关键的数据,因为当你遇到跟GC有关的问题,诸如过度GC、内存泄露等问题是,你将可以利用这些线程的原生Id值关联的操作系统或者Java线程,进而发现任何对CPI时间的高占用. 未来的文章你将会了解到如何识别并诊断这样的问题.

# JNI 全局引用计数
JNI (Java 本地接口)的全局引用就是从本地代码到由Java垃圾收集器管理的Java对象的基本的对象引用. 它的角色就是阻止对仍然在被本地代码使用,但是技术上已经不是Java代码中的“活动的”引用了的对象的垃圾收集.

同时为了侦测JNI相关的泄露而留意JNI引用也很重要. 如果你的程序直接使用了JNI,或者像监听器这样的第三方工具,就容易造成本地的内存泄露.
 
JNI global references: 1925

# Java 堆栈使用视图


这些数据被添加回了 JDK 1 .6 ,向你提供有关Hotspot堆栈的一个简短而快速的视图. 我发现它在当我处理带有过高CPU占用的GC相关的问题时非常有用,你可以在一个单独的快照中同时看到线程堆栈以及Java堆的信息,让你当时就可以在一个特定的Java堆内存空间中解析(或者排除)出任何的关键点. 你如在我们的示例线程堆栈中所见,Java 的堆 OldGen 超出了最大值!

Heap
 PSYoungGen   total 466944K, used 178734K [0xffffffff45c00000, 0xffffffff70800000, 0xffffffff70800000)
 eden space 233472K, 76% used [0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000)
 from space 233472K, 0% used [0xffffffff62400000,0xffffffff62400000,0xffffffff70800000)
 to  space 233472K, 0% used [0xffffffff54000000,0xffffffff54000000,0xffffffff62400000)
 PSOldGen    total 1400832K, used 1400831K [0xfffffffef0400000, 0xffffffff45c00000, 0xffffffff45c00000)
 object space 1400832K, 99% used [0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000)
 PSPermGen    total 262144K, used 248475K [0xfffffffed0400000, 0xfffffffee0400000, 0xfffffffef0400000)
 object space 262144K, 94% used [0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee040000

更多Detaillierte JVM-Analyse des Java-Thread-Stacks相关文章请关注PHP中文网!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn