5
votes

[Update: in top, after I pressed shift+H, which shows threads rather than processes, it then shows the Java thread as R and using 100% CPU time, which is what I expected before posting this question.]

Since a Java process has multiple threads, each of which might be in a different state, then how does Linux top command determine the Java process state?

If I run the following code,

public class Test{
  public static void main(String[] args){
     while (true){
       int n = (int)(Math.random() * 1000);
     }
  }
}

Then, running top shows that the process state is S, and it's using 100% CPU time.

Also, running strace shows and only shows:

futex(0x7f6ba759c9d0, FUTEX_WAIT, 26060, NULL

However, running jstack shows that the main thread is RUNNABLE:

"main" prio=10 tid=0x00007fd7ec007800 nid=0x669b runnable [0x00007fd7f5754000]
  java.lang.Thread.State: RUNNABLE
    at Test.main(Test.java:5)

jstack also shows that, there are only two threads in WAITING state:

"Finalizer" daemon prio=10 tid=0x00007fd7ec080000 nid=0x66a6 in Object.wait() [0x00007fd7f0252000]
    java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007ad001310> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133)
        - locked <0x00000007ad001310> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)

"Reference Handler" daemon prio=10 tid=0x00007fd7ec07e000 nid=0x66a5 in Object.wait() [0x00007fd7f0353000]
    java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007ad0011e8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
        - locked <0x00000007ad0011e8> (a java.lang.ref.Reference$Lock)
4
The top command aggregates information by process (pid). You can see how many threads total for a process by scoping the command with -o th. The usage statistics are aggregated from the active thread for the process. - Perception

4 Answers

2
votes

A JVM has many threads running to do "housekeeping" like garbage collection, etc. Those are in sleep state most of the time.

1
votes

Then, running top shows that the process state is S, and it's using 100% CPU time.

I think that the issue is most likely with the way that top is determining the process status. At the OS level, it is individual threads that have a run/wait/sleep state. My guess is that the top command's heuristic for figuring out a notional run/wait/sleep state for the process is misleading.

(And the output from jstack ... and common sense ... support this theory.)

0
votes

This thread is busily using a CPU, it is not sleeping.

"main" prio=10 tid=0x00007fd7ec007800 nid=0x669b runnable [0x00007fd7f5754000]
  java.lang.Thread.State: RUNNABLE
    at Test.main(Test.java:5)

This suggests the information in top is not correct.

0
votes

There's been a lot of explanation of "why you have multiple threads, and what they do in Java", but not that much on what. The top command itself is fairly simple, in that it just goes through the system calls necessary to gather information - for example getrusage is used to fetch the CPU usage.

Typically, as explained, top looks at a whole process, all threads at once. You can press "H" in top and it will show individual threads instead of whole process, and you would then be able to see all your Java threads [if your screen is high enough], where the main one is using all the CPU in your infinite loop, and the other threads are mainly doing nothing.