1

I am trying to understand what the "cpu" and "elapsed" fields mean in a jstack thread dump in java 11. I have the following details for a thread, where jstack was executed three times quickly:

"Thread 1 " daemon prio=5 os_prio=0 cpu=0.13ms elapsed=51.03s tid=0x00007fe9c4024000 nid=0x2c11 waiting on condition  [0x00007fe500284000]
   java.lang.Thread.State: TIMED_WAITING (parking)
"Thread 1 " daemon prio=5 os_prio=0 cpu=0.13ms elapsed=56.96s tid=0x00007fe9c4024000 nid=0x2c11 waiting on condition  [0x00007fe500284000]
   java.lang.Thread.State: TIMED_WAITING (parking)
"Thread 2" daemon prio=5 os_prio=0 cpu=0.10ms elapsed=1.35s tid=0x00007fe9c4024000 nid=0x2da1 waiting on condition  [0x00007fe4a0311000]
   java.lang.Thread.State: TIMED_WAITING (parking)

After TIMED_WAITING, rest of the message is exactly same in all the three threads. My question is, why does elapsed time suddenly decrease on the third 1, even when tid is the same? In my application, thread name keeps changing, so it doesn't necessarily imply that a different thread name corresponds to a different thread. Can it happen that the old thread died and the same tid was quickly reused? If someone could link any official doc on the explanation of the dump, that would be helpful. (NOTE: My threads belong to a thread pool)

I could only find the cpu and elapsed explanation at https://bugs.openjdk.org/browse/JDK-8200720. But doesn't really help.

1 Answers1

1

The third output obviously contains a different thread. If you do not trust the different name, trust the different nid. Further, taking the output “elapsed=1.35s” for granted, it literally means that the thread only ran for a bit more than a second at this point, so it’s perfectly plausible that the thread has been started between your jstack calls.

When your third jstack output does not contain the first thread and you didn’t filter, it indicates that the first thread has terminated in-between the second and third call, which explains why these two threads can have the same tid. Since this is not a thread id but a memory address, freeing the old thread object allows to reuse the memory for a new thread object.

As said, use the nid instead, to decide whether you are looking at the same or a different thread.

You can find different articles explaining the attributes in the internet, but I could not find one that qualifies as an official documentation, though.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • https://stackoverflow.com/questions/14791278/threads-why-must-all-user-threads-be-mapped-to-a-kernel-thread this says that the mapping between user thread and kernel thread is not one to one. I am trying to trace back from the source code of openjdk but I am lost. I tried looking at the number written with the '#' after the thread name (in the stack trace I wrote here, there was also a # with an ID after the name, like #5), I suspect that that is unique. I tried looking at the source code and although I couldn't rigorously prove it, some sort of addition by one is being done to compute this. – user22058606 Jun 16 '23 at 18:40
  • 1
    What you’ve linked, is a very general answer while we’re looking at a particular implementation here. This implementation does a one-to-one mapping for a very long time now and won’t change that. Instead, the upcoming feature of Virtual Threads will reintroduce the concept of threads not directly mapped to kernel threads, however, that feature has to be requested explicitly. For your problem, you can assume a one-to-one mapping. But I think, this ID after the `#` is unique too. – Holger Jun 19 '23 at 07:48
  • can you give a reference which indicates a one to one mapping in this implementation. – user22058606 Jun 20 '23 at 08:18
  • 1
    For example, [here](https://openjdk.org/jeps/425#Description): “*Today, every instance of java.lang.Thread in the JDK is a platform thread. A platform thread runs Java code on an underlying OS thread and captures the OS thread for the code's entire lifetime.*” – Holger Jun 20 '23 at 10:12