Unfortunately, this is wrong interpretation of the numbers.
I’ve faced this situation many times (and ask a question on stackoverflow too).
The main reason, is VisualVM doesn’t show correct CPU time. It showing percentage of the thread time in RUNNING
state. But from documentation on Thread.State
:
Thread state for a runnable thread. A thread in the runnable
state is executing in the Java virtual machine but it may
be waiting for other resources from the operating system
such as processor.
This is exactly what’s going on. Actually, thread is blocked inside OS epoll_wait()
call. On Linux box there are several ways you can confirm it’s the case.
strace
‘ing thread
$ strace -tttT -f -p [thread-id]
Thread id could be obtained from jstack
output:
$ jstack [java-pid]
[...]
"Netty Builtin Server 1" #17 prio=5 os_prio=31 tid=0x00000001013dd800 nid=0xe12f runnable [0x0000700001fe4000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.KQueueArrayWrapper.kevent0(Native Method)
at sun.nio.ch.KQueueArrayWrapper.poll(KQueueArrayWrapper.java:198)
[...]
in this case thread id is 0xe12f
(should be converted to decimal). You will see the most of the time thread will be in epoll_wait()
call.
pidstat
ing thread
$ pidstat -tu -p [java-pid] | grep [thread pid]
you will see low system as well as user CPU time by this thread, meaning it doesn’t consume CPU.
polling thread state using ps
$ ps -eL -o pid,tid,state | grep [thread-id]
you will see most of the time thread in state S
or Sl
(interruptible sleep) instead of R
(runnable).
In the end you should not worrying about that if there are no operational issues with the service.