Java 스레드 덤프는 JVM에서 활성화된 모든 스레드의 목록입니다.
Java 스레드 덤프
Java 스레드 덤프는 응용 프로그램의 병목 현상 및 데드락 상황을 분석하는 데 매우 유용합니다. 여기에서는 Java 프로그램에 대해 스레드 덤프를 생성하는 다양한 방법을 배울 것입니다. 이 지침은 *nix 운영 체제에서 유효하지만, Windows에서는 단계가 약간 다를 수 있습니다.
- VisualVM Profiler: 응용 프로그램의 지연을 분석하는 경우 프로파일러를 사용해야 합니다. VisualVM 프로파일러를 사용하여 어떤 프로세스에 대한 스레드 덤프를 생성하는 것은 매우 쉽습니다. 실행 중인 프로세스를 마우스 오른쪽 버튼으로 클릭하고 “Thread Dump” 옵션을 클릭하면 덤프를 생성할 수 있습니다.
- jstack: Java에는 스레드 덤프를 생성할 수 있는 jstack 도구가 함께 제공됩니다. 이는 두 단계로 이루어진 프로세스입니다.
ps -eaf | grep java
명령을 사용하여 Java 프로세스의 PID를 찾습니다.- 스레드 덤프 출력을 콘솔에 생성하기 위해
jstack PID
로 jstack 도구를 실행할 수 있으며, 명령 “jstack PID >> mydumps.tdump”을 사용하여 스레드 덤프 출력을 파일에 추가할 수 있습니다.
kill -3 PID
명령을 사용하여 스레드 덤프를 생성할 수 있습니다. 이 방법은 다른 스레드 덤프 생성 방법과 약간 다릅니다. kill 명령이 발행되면 프로그램의 시스템 출력에 스레드 덤프가 생성됩니다. 따라서 콘솔을 시스템 출력으로 사용하는 자바 프로그램인 경우 스레드 덤프가 콘솔에 인쇄됩니다. 자바 프로그램이 시스템 출력을catalina.out
으로 하는 Tomcat 서버인 경우, 스레드 덤프가 파일에 생성됩니다.- 자바 8에서는
jcmd
유틸리티가 도입되었습니다. Java 8 이상인 경우 jstack 대신 이를 사용해야 합니다. jcmd를 사용하여 스레드 덤프를 생성하는 명령어는 다음과 같습니다.jcmd PID Thread.print
.
위에 나열된 것은 자바에서 스레드 덤프를 생성하는 네 가지 다른 방법입니다. 보통 jstack 또는 jcmd 명령을 사용하여 스레드 덤프를 생성하고 분석하는 것을 선호합니다. 선택한 방법이 무엇이든 스레드 덤프는 항상 동일합니다.
자바 스레드 덤프 예제
지난 게시물에서 자바 Timer에 대해 설명했었습니다. 이와 동일한 프로그램에 대한 스레드 덤프가 생성되었습니다.
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
쓰레드 덤프는 모든 스레드 목록입니다. 각 항목은 다음과 같은 순서로 스레드에 관한 정보를 보여줍니다.
- 쓰레드 이름: 쓰레드의 이름
- 쓰레드 우선순위: 쓰레드의 우선순위
- 쓰레드 식별자: 쓰레드의 고유 식별자
- 쓰레드 상태: 현재 쓰레드 상태를 제공합니다. 예를 들어, RUNNABLE, WAITING, BLOCKED입니다. 데드락을 분석할 때, 차단된 스레드와 그들이 잠금을 얻으려고 시도하는 리소스를 찾아보세요.
- 쓰레드 콜스택: 쓰레드에 대한 중요한 스택 정보를 제공합니다. 여기서는 쓰레드가 획득한 잠금과 대기 중인 잠금을 볼 수 있습니다.
이것이 자바의 쓰레드 덤프에 관한 모든 내용입니다.
Source:
https://www.digitalocean.com/community/tutorials/java-thread-dump-visualvm-jstack-kill-3-jcmd