Java - How to Get Thread Details

Subscribe Send me a message home page tags


#java  #profiling  #thread  #probe  #run-time analysis 

In this post, we will describe two different ways to obtain the thread details of a running Java program.

Method 1

If we have access to the source code, we could print the stack trace of running threads. The two methods involved are

Here is the demo code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package language;

import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class ThreadDetailDemo {

    private static void run() {
        int threadId = (int) (Math.random() * 100);

        try {
            while (true) {
                int waitingTime = (int) (Math.random() * 10) + 5;
                System.out.println("Thread ID: " + threadId + ", waiting time: " + waitingTime + " s");
                Thread.sleep(waitingTime * 1000);
            }
        } catch (final InterruptedException e) {
            return;
        }
    }

    private static void displayThreadInformation() {
        for (final Thread thread : Thread.getAllStackTraces().keySet()) {
            System.out.println("thread - ++++++++++++++++");
            System.out.println("thread - " + thread.getName());
            System.out.println("thread - " + thread.toString());
            final String stackTrace = String.join("\n",
                    Arrays.stream(thread.getStackTrace())
                    .map(StackTraceElement::toString)
                    .collect(Collectors.toList()));

            System.out.println("thread - " + stackTrace);
        }
    }

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        executorService.execute(ThreadDetailDemo::run);
        executorService.execute(ThreadDetailDemo::run);

        Thread.sleep(5000);
        displayThreadInformation();
    }
}

Here is an exmaple of a reported thread:

thread - ++++++++++++++++
thread - pool-1-thread-1
thread - Thread[pool-1-thread-1,5,main]
thread - java.base@11.0.2/java.lang.Thread.sleep(Native Method)
app//language.ThreadDetailDemo.run(ThreadDetailDemo.java:18)
app//language.ThreadDetailDemo$$Lambda$14/0x0000000800066840.run(Unknown Source)
java.base@11.0.2/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base@11.0.2/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
java.base@11.0.2/java.lang.Thread.run(Thread.java:834)

As we can see in the output, the stack trace contains the definition of the running task. In this example, we could tell the task is ThreadDetailDemo.run. we could also tell the thread is created by a ThreadPoolExecutor but unfortunately, we don't have more details of the creator of this thread.

The following threads are reported by the displayThreadInformation method:

Thread[Common-Cleaner,8,InnocuousThreadGroup]
Thread[Finalizer,8,system]
Thread[Monitor Ctrl-Break,5,main]
Thread[Reference Handler,10,system]
Thread[Signal Dispatcher,9,system]
Thread[main,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-2,5,main]

Method 2

If we don't have access to the source code or we cannot stop the running program, we could use the jstack utility. The usage is quite simple:

Here is a sample output:

"pool-1-thread-1" #12 prio=5 os_prio=31 cpu=49.29ms elapsed=530.67s tid=0x00007f86908c3000 nid=0x5a03 waiting on condition  [0x000070000c779000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(java.base@11.0.2/Native Method)
	at language.ThreadDetailDemo.run(ThreadDetailDemo.java:18)
	at language.ThreadDetailDemo$$Lambda$14/0x0000000800066840.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.2/ThreadPoolExecutor.java:1128)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.2/ThreadPoolExecutor.java:628)
	at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

Notice that the jstack tool reports more threads. For example, it reports GC threads. Here is the list of threads reported by jstack

"Attach Listener" #15 daemon prio=9 os_prio=31 cpu=1.83ms elapsed=292.40s tid=0x00007f868f827800 nid=0x5d03 waiting on condition  [0x0000000000000000]
"C1 CompilerThread0" #7 daemon prio=9 os_prio=31 cpu=167.23ms elapsed=531.18s tid=0x00007f8690860800 nid=0x3a03 waiting on condition  [0x0000000000000000]
"C2 CompilerThread0" #5 daemon prio=9 os_prio=31 cpu=153.22ms elapsed=531.19s tid=0x00007f8690075800 nid=0x3d03 waiting on condition  [0x0000000000000000]
"Common-Cleaner" #9 daemon prio=8 os_prio=31 cpu=0.81ms elapsed=530.95s tid=0x00007f869085a000 nid=0xa603 in Object.wait()  [0x000070000c36d000]
"DestroyJavaVM" #14 prio=5 os_prio=31 cpu=332.44ms elapsed=525.63s tid=0x00007f868f829800 nid=0x1703 waiting on condition  [0x0000000000000000]
"Finalizer" #3 daemon prio=8 os_prio=31 cpu=0.40ms elapsed=531.27s tid=0x00007f869085f800 nid=0x3603 in Object.wait()  [0x000070000bd58000]
"G1 Conc#0" os_prio=31 cpu=0.04ms elapsed=531.30s tid=0x00007f869080b000 nid=0x3003 runnable
"G1 Main Marker" os_prio=31 cpu=1.72ms elapsed=531.30s tid=0x00007f8690030000 nid=0x5103 runnable
"G1 Refine#0" os_prio=31 cpu=2.02ms elapsed=531.30s tid=0x00007f8690070000 nid=0x4f03 runnable
"G1 Young RemSet Sampling" os_prio=31 cpu=84.35ms elapsed=531.30s tid=0x00007f868f808800 nid=0x3103 runnable
"GC Thread#0" os_prio=31 cpu=1.62ms elapsed=531.30s tid=0x00007f8691010000 nid=0x5203 runnable
"Monitor Ctrl-Break" #10 daemon prio=5 os_prio=31 cpu=26.40ms elapsed=530.69s tid=0x00007f868f8bc800 nid=0xa403 runnable  [0x000070000c470000]
"Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.18ms elapsed=531.27s tid=0x00007f868f81c000 nid=0x3503 waiting on condition  [0x000070000bc55000]
"Service Thread" #11 daemon prio=9 os_prio=31 cpu=0.05ms elapsed=530.69s tid=0x00007f868f8bf800 nid=0x5803 runnable  [0x0000000000000000]
"Signal Dispatcher" #4 daemon prio=9 os_prio=31 cpu=0.66ms elapsed=531.20s tid=0x00007f8691028000 nid=0x4003 runnable  [0x0000000000000000]
"Sweeper thread" #8 daemon prio=9 os_prio=31 cpu=2.97ms elapsed=531.17s tid=0x00007f8690859800 nid=0xa803 runnable  [0x0000000000000000]
"VM Periodic Task Thread" os_prio=31 cpu=401.66ms elapsed=530.68s tid=0x00007f86908c1800 nid=0xa003 waiting on condition
"VM Thread" os_prio=31 cpu=25.51ms elapsed=531.28s tid=0x00007f8690073800 nid=0x3303 runnable
"pool-1-thread-1" #12 prio=5 os_prio=31 cpu=49.29ms elapsed=530.67s tid=0x00007f86908c3000 nid=0x5a03 waiting on condition  [0x000070000c779000]
"pool-1-thread-2" #13 prio=5 os_prio=31 cpu=58.26ms elapsed=530.67s tid=0x00007f8691035000 nid=0x9d03 waiting on condition  [0x000070000c87c000]

----- END -----

If you have questions about this post, you could find me on Discord.
Send me a message Subscribe to blog updates

Want some fun stuff?

/static/shopping_demo.png