Java Thread Dump – תזרים של תהליכים ב-Java – VisualVM, jstack, kill -3, jcmd

תצוגת Thread ב-Java היא רשימה של כל הטראדים הפעילים ב-JVM.

תצוגת טראד ב-Java

תצוגת טראד ב-Java עוזרת מאוד בניתוח הסתסכויות ביישום ובמצבי קיבוע. כאן נלמד כמה דרכים שונות ליצירת תצוגת טראד עבור תוכנית ג'אווה. ההוראות האלו תקפות למערכות הפעלה *nix, אך בחלונות השלבים עשויים להיות מעט שונים.

  1. פרופילר VisualVM: אם אתה ניתוח את היישום בשביל לזהות איטיות, עליך להשתמש בפרופילר. אנחנו יכולים ליצור תצוגת טראד עבור כל תהליך באמצעות הפרופילר VisualVM בצורה פשוטה מאוד. יש רק להקליק ימני על התהליך הפועל וללחוץ על אפשרות "Thread Dump" כדי ליצור אותה.
  2. jstack: ב-Java יש כלי בשם jstack שבאמצעותו אנחנו יכולים ליצור תצוגת טראד עבור תהליך ג'אווה. זה תהליך שבשני שלבים.
    1. מציאת ה-PID של תהליך ה-Java באמצעות הפקודה ps -eaf | grep java
    2. הרצת כלי jstack כ-jstack PID כדי ליצור את תצוגת הטראד לפלט המסופק למסך, ניתן להוסיף את פלט תצוגת הטראד לקובץ באמצעות הפקודה "jstack PID >> mydumps.tdump"
  3. ניתן להשתמש בפקודת kill -3 PID כדי ליצור את ה- thread dump. זה מעט שונה מדרכים אחרות ליצור thread dump. כאשר ניתן את הפקודה להרוג, נוצר thread dump במערכת הפלט של התוכנית. אם זו תוכנית Java עם פלט מערכת כמערכת המשלוח, אז ה-thread dump יתווסף על המסך. אם התוכנית Java היא שרת Tomcat עם מערכת הפלט כ-catalina.out, אז thread dump יתווסף בקובץ.
  4. Java 8 הכניסה את התועלת jcmd. עליך להשתמש בזה במקום jstack אם אתה ב-Java 8 או גרסה גבוהה יותר. הפקודה ליצירת thread dump באמצעות jcmd היא jcmd PID Thread.print.

לעיל הן ארבע דרכים שונות ליצירת thread dump ב-Java. כללית אני מעדיף את פקודת jstack או jcmd ליצירת thread dump וניתוח. שים לב שבכל דרך שתבחר, thread dump תמיד יהיה זהה.

דוגמה על תהליך ה-Java Thread Dump

בפוסט האחרון שלי, הסברתי על java Timer, והנה thread dump שנוצר עבור אותו תוכנית.

2012-12-26 22:28:39
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode):

"Attach Listener" daemon prio=5 tid=0x00007fb7d8000000 nid=0x4207 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Timer-0" daemon prio=5 tid=0x00007fb7d4867000 nid=0x5503 waiting on condition [0x00000001604d9000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.journaldev.threads.MyTimerTask.completeTask(MyTimerTask.java:19)
	at com.journaldev.threads.MyTimerTask.run(MyTimerTask.java:12)
	at java.util.TimerThread.mainLoop(Timer.java:555)
	at java.util.TimerThread.run(Timer.java:505)

"Service Thread" daemon prio=5 tid=0x00007fb7d482c000 nid=0x5303 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=5 tid=0x00007fb7d482b800 nid=0x5203 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=5 tid=0x00007fb7d4829800 nid=0x5103 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=5 tid=0x00007fb7d4828800 nid=0x5003 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=5 tid=0x00007fb7d4812000 nid=0x3f03 in Object.wait() [0x000000015fd26000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x0000000140a25798> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
	- locked <0x0000000140a25798> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)

"Reference Handler" daemon prio=5 tid=0x00007fb7d4811800 nid=0x3e03 in Object.wait() [0x000000015fc23000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x0000000140a25320> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:503)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
	- locked <0x0000000140a25320> (a java.lang.ref.Reference$Lock)

"main" prio=5 tid=0x00007fb7d5000800 nid=0x1703 waiting on condition [0x0000000106116000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.journaldev.threads.MyTimerTask.main(MyTimerTask.java:33)

"VM Thread" prio=5 tid=0x00007fb7d480f000 nid=0x3d03 runnable 

"GC task thread#0 (ParallelGC)" prio=5 tid=0x00007fb7d500d800 nid=0x3503 runnable 

"GC task thread#1 (ParallelGC)" prio=5 tid=0x00007fb7d500e000 nid=0x3603 runnable 

"GC task thread#2 (ParallelGC)" prio=5 tid=0x00007fb7d5800000 nid=0x3703 runnable 

"GC task thread#3 (ParallelGC)" prio=5 tid=0x00007fb7d5801000 nid=0x3803 runnable 

"GC task thread#4 (ParallelGC)" prio=5 tid=0x00007fb7d5801800 nid=0x3903 runnable 

"GC task thread#5 (ParallelGC)" prio=5 tid=0x00007fb7d5802000 nid=0x3a03 runnable 

"GC task thread#6 (ParallelGC)" prio=5 tid=0x00007fb7d5802800 nid=0x3b03 runnable 

"GC task thread#7 (ParallelGC)" prio=5 tid=0x00007fb7d5803800 nid=0x3c03 runnable 

"VM Periodic Task Thread" prio=5 tid=0x00007fb7d481e800 nid=0x5403 waiting on condition 

JNI global references: 116

רשימת התהליכים היא רשימת כל התהליכים, כל ערך מציג מידע על התהליך שכולל את הפרטים הבאים בסדרם.

  1. שם התהליך: שם התהליך
  2. עדיפות התהליך: עדיפות התהליך
  3. מזהה התהליך: מייצג את המזהה הייחודי של התהליך
  4. מצב התהליך: מספק את המצב הנוכחי של התהליך, לדוגמה RUNNABLE, WAITING, BLOCKED. בעת ניתוח נעילת מעגל מתבצע חיפוש אחר תהליכים נעולים ואת המשאבים עליהם הם מנסים להשיג נעילה.
  5. מחסנית של התהליך: מספקת מידע חיוני על המחסנית עבור התהליך. זהו המקום בו אנו יכולים לראות את הנעילות שנרכשו על ידי התהליך ואם הוא ממתין לנעילה כלשהי.

זהו הכל לרשימת התהליכים ב-Java.

Source:
https://www.digitalocean.com/community/tutorials/java-thread-dump-visualvm-jstack-kill-3-jcmd