Thread Dump Analysis and Java Flight Recorder
Java Flight Recording is an excellent tool for diagnosing abnormalities in production. The overhead of JFR is very minimal. In Java Flight Recording, you can analyze thread dumps deeply.
Before analyzing the Thread Dumps output, we have to know how to read Thread states
A thread can be in one of the following states:
- NEW : A thread that has not yet started is in this state.
- RUNNABLE : A thread executing in the Java virtual machine is in this state.
- BLOCKED : A thread that is blocked waiting for a monitor lock is in this state.
- WAITING : A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
- TIMED_WAITING : A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
- TERMINATED : A thread that has exited is in this state.
In this post, I’ll go over the RUNNABLE, WAITING, and TIMED_WAITING states in depth. In order to understand how states work, I wrote a simple application like below:
What would happen if we took a dump just after triggering a dump? Here are the answers :
“main” prio=5 Id=1 RUNNABLE
at java.management@11.0.5/sun.management.ThreadImpl.dumpThreads0(Native Method)
at java.management@11.0.5/sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:502)
at java.management@11.0.5/sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:490)
at app//jug.istanbul.thread_dump.WaitingStatesDemo.threadDump(WaitingStatesDemo.java:27)
at app//jug.istanbul.thread_dump.WaitingStatesDemo.main(WaitingStatesDemo.java:12)
“Thread-0” prio=5 Id=14 TIMED_WAITING
at java.base@11.0.5/java.lang.Thread.sleep(Native Method)
at app//jug.istanbul.thread_dump.ThreadA.run(ThreadA.java:13)
— locked jug.istanbul.thread_dump.ThreadA@2ef5e5e3
The main thread is in a RUNNING state and Thread-0, which is ThreadA, is in a TIMED_WAITING state. It means Thread-0 is sleeping.
Now I got another thread dump from Thread A after the sleep(5000) method.
“main” prio=5 Id=1 WAITING on jug.istanbul.thread_dump.ThreadA@17cb4dde owned by “Thread-0” Id=14
at java.base@11.0.5/java.lang.Object.wait(Native Method)
— waiting on jug.istanbul.thread_dump.ThreadA@17cb4dde
at java.base@11.0.5/java.lang.Object.wait(Object.java:328)
at app//jug.istanbul.thread_dump.WaitingStatesDemo.main(WaitingStatesDemo.java:16)
“Thread-0” prio=5 Id=14 RUNNABLE
at java.management@11.0.5/sun.management.ThreadImpl.dumpThreads0(Native Method)
at java.management@11.0.5/sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:502)
at java.management@11.0.5/sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:490)
at app//jug.istanbul.thread_dump.WaitingStatesDemo.threadDump(WaitingStatesDemo.java:27)
at app//jug.istanbul.thread_dump.ThreadA.run(ThreadA.java:16)
— locked jug.istanbul.thread_dump.ThreadA@17cb4dde
The main thread is in a WAITING state and Thread-0 is in a RUNNING state. It means Thread-0 is sleeping.
In order to get thread dump I use below method:
public 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();
}
Be lean…