Are your Java threads consuming most of your CPU and want to find which one is actually consuming most of it? Then just keep reading.
There are several solutions to detect which Java thread is consuming more CPU.
Use JVisualVM to detect CPU bottlenecks
If you have installed JVisualVM, then you can connect to the remote machine and view the CPU utilization, memory sampling, threads.
In the Thread CPU Time sub-panel you can view how much CPU time is being spent by each thread. This allows you to inspect CPU time since the sampling started (Thread CPU Time [ms]) and instantly (Thread CPU Time [ms/sec], on the far right).
Use the top command to detect CPU bottlenecks
JVisualVM is pretty useful but not always an option and furthermore it adds a substantial extra burden on the machine to run these tools
In order to have a complete insight on the threads running on the application server, we could just use the command line and we will show how to do that.
Step 1: find the Java process
You can detect the Java process in many ways, however the 'jps' tool (part of the JDK) is the simplest:
$ jps -v 11218 Jps -Dapplication.home=/usr/lib/jvm/java-1.8.0-openjdk-22.214.171.124.b13-0.fc29.x86_64 -Xms8m 10824 jboss-modules.jar -D[Standalone] -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true -Dorg.jboss.boot.log.file=/home/francesco/jboss/wildfly-19.0.0.Final/standalone/log/server.log -Dlogging.configuration=file:/home/francesco/jboss/wildfly-19.0.0.Final/standalone/configuration/logging.properties
So we have a WildFly server running with process id 11218. Now we will use the top utility to detect which Java thread is consuming most of the CPU:
Step 2: find the Java threads consuming CPU
On Linux and Unixsystems, you can use the top command against our Java process (11218) as follows:
$ top -n 1 -H -p 11218
Please notice we are using the -H option (Threads toggle). When this toggle is On, all individual threads will be displayed. Otherwise, top displays a summation of all threads in a process.
On Solaris, you can use the prstat command:
$ prstat -L -p 11218
Step 3: find the corresponding Java Hex Thread id
In our case, the top revealed that three java processes (10841, 10957 and 10958) are consuming almost 7% of the CPU time. Now the twist is that the Thread id used by Java Thread dumps uses an Hex notation for Threads' id. Don’t panic, let’s use the printf function to calculate the Hex notation for our pid:
$ printf 0x%x 10841 0x2a59
As you will see, the process id of the light weight process (0x2a59) corresponds to the nid attribute of Java Thread dump. So here’s how to find the related Thread which is causing your CPU to slow down:
$ jstack -l 11218 | grep "0x2a59" "default I/O-7" #95 prio=5 os_prio=0 tid=0x00007fe714151000 nid=0x2c4c runnable [0x00007fe6d79f8000]
So there's some I/O processing in the Thread which is consuming lots of CPI. Further inspection of this Thread’s Stack trace will help you to get closer to the solution of the problem.
Programmatically find which Thread is consuming your CPU
If you prefer a programmatic approach to finding the CPU usage of threads, then you can have a look at the java.lang.management.ThreadMXBean class, which is part of the JMX management API. How to use this class in the context of the application server is discussed in detail in the "Hacking JMX " section of this book. In a nutshell, once you have collected the ThreadMXBean from the ManagementFactory:
ThreadMXBean tmxb = ManagementFactory.getThreadMXBean(); // Then you can query how much a specific thread is consuming by using: long cpuTime = tmxb.getThreadCpuTime(aThreadID);
Use jvmtop to find which thread is consuming your CPU
jvmtop is a lightweight console application to monitor all accessible, running jvms on a machine. In a top-like manner, it displays JVM internal metrics (e.g. memory information) of running java processes. Jvmtop does also include a CPU console profiler.
You can find the project here: https://github.com/patric-r/jvmtop
Once run, you can easily capture the list of threads which are hogging your CPU. Example output:
jvmtop.sh <pid> JvmTop 0.4.1 alpha amd64, 4 cpus, Linux 2.6.18-34 PID 3539: org.apache.catalina.startup.Bootstrap ARGS: start VMARGS: -Djava.util.logging.config.file=/home/webserver/apache-tomcat-5.5[...] VM: Sun Microsystems Inc. Java HotSpot(TM) 64-Bit Server VM 1.6.0_25 UP: 869:33m #THR: 106 #THRPEAK: 143 #THRCREATED: 128020 USER: webserver CPU: 4.55% GC: 3.25% HEAP: 137m / 227m NONHEAP: 75m / 304m Note: Only top 10 threads (according cpu load) are shown! TID NAME STATE CPU TOTALCPU BLOCKEDBY 25 http-8080-Processor13 RUNNABLE 4.55% 1.60% 128022 RMI TCP Connection(18)-10.101. RUNNABLE 1.82% 0.02% 36578 http-8080-Processor164 RUNNABLE 0.91% 2.35% 36453 http-8080-Processor94 RUNNABLE 0.91% 1.52% 27 http-8080-Processor15 RUNNABLE 0.91% 1.81% 14 http-8080-Processor2 RUNNABLE 0.91% 3.17% 128026 JMX server connection timeout TIMED_WAITING 0.00% 0.00% 128025 JMX server connection timeout TIMED_WAITING 0.00% 0.00% 128024 JMX server connection timeout TIMED_WAITING 0.00% 0.00% 128023 JMX server connection timeout TIMED_WAITING 0.00% 0.00%
We have just covered some handy solutions to detect which Java process most of the CPU on a Linux/Unix system.