How to identify Java threads consuming CPU

java
how-to

#1

Objective

This article gives you assistance on identifying which thread is consuming CPU in a Java process in OpenNMS. It is a useful technique when you experience high CPU under load.

Solution

You can identify which thread is consuming CPU in a Java process.

Step 1: Get the Java process ID (PID) from the running OpenNMS application.

Run systemctl status opennms and note the main PID or look into ${OPENNMS_HOME}/logs/opennms.pid. If you run on a Windows system you use the Java provided command jps -v.

Step 2: Determine which thread in the PID identified in Step 1 is consuming the CPU

Replace ${pid} with the process ID of the affected process.

  • On Unix and Linux systems
    top -n 1 -H -p ${pid}
    
  • On Microsoft Windows you can use the Process Monitor

These commands all give an output listing all the threads in the selected process along with various details, including the CPU usage percentage. For example, the top command gives an output similar to this:

Tasks: 152 total,   0 running, 152 sleeping,   0 stopped,   0 zombie 
Cpu(s):  2.0%us,  1.4%sy,  0.0%ni, 94.7%id,  0.8%wa,  0.0%hi,  1.1%si,  0.0%st 
Mem:   5008484k total,  4854428k used,   154056k free,    85624k buffers 
Swap:  5013496k total,     6516k used,  5006980k free,  3393948k cached
PID  USER     PR  NI  VIRT  RES  SHR S  %CPU  %MEM   TIME+  COMMAND              
8706 user.1   20   0 2433m 561m  10m R  32.0  11.5  0:35.45 java
8624 user.1   20   0 2433m 561m  10m S   0.0  11.5  0:00.01 java                 
8625 user.1   20   0 2433m 561m  10m S   0.0  11.5  0:10.12 java                 
8626 user.1   20   0 2433m 561m  10m S   0.0  11.5  0:35.60 java                 
8627 user.1   20   0 2433m 561m  10m S   0.0  11.5  0:00.01 java                 
8628 user.1   20   0 2433m 561m  10m S   0.0  11.5  0:00.02 java              

In this example, we can see that thread ID 8706 is consuming 32% of the CPU.

Step 3: Produce a stack trace for the PID identified in step 1

jstack ${pid} > jstack-output.txt

Step 4: Convert the thread ID identified as problematic in step 2 to a hex value.

In the example above the thread ID decimal value 8706 converts to hex value 2202.

You a use an online hex-converter for convenience.

Step 5: Search the stack trace output for this hex value

You are looking for a thread that matches the hex value: 2202

cat jstack-output.txt | grep -i 2202

This command gives an output similar to this:

"Concurrent Mark-Sweep GC Thread" prio=10 tid=0x00007f1448029800 nid=0x2202 runnable

In this example, we can see that the problem is a Garbage Collector (GC) thread.