Kiryl Klachkou
Kiryl Klachkou

Reputation: 33

Live monitoring of total thread stack size in Java

As I know in Java thread stack size depends on JVM and OS Architecture and by default (unless -Xss is set) varies between 256k and 1m. Is there a way or tool allowing to see total stack size consumed by all currently running threads in runtime like I can see Heap Size or Metaspace Size using JVisualVM from JDK package? I understand that this value can be calculated as thread stack size * number of currently running threads however it would be great to monitor this value in runtime.

Upvotes: 0

Views: 3261

Answers (2)

Stephen C
Stephen C

Reputation: 718768

First of all, the default stack size is platform specific, but that does not mean that the platform specific default "varies". My recollection is that the defaults have not changed (for any given "architecture") for a long time. (Probably since Java 5, if not earlier. But don't quote me!)

You also can't use the default to accurately determine how much stack memory has actually been allocated, since:

  1. The platform default can be overridden via the -xss command line option. As you noted.
  2. A non-default stack size can be specified when each Thread object is created.
  3. The stack is only actually allocated when the Thread is started. (And it is deallocated when the Thread terminates.)

So if you wanted to measure the actual allocated stack memory you would need to iterate all of the threads and find their actual stack sizes. The first should be relatively straight forwards: traverse the ThreadGroup tree. (I don't think you can guarantee that you will see all threads in a traversal, but that shouldn't matter.) The second is more difficult since there is no getter for the private Thread.stackSize field ... and that field only records the parameter that the application supplied to the Thread constructor.

However, since typical applications just use the default stack size, counting the threads and multiplying by the default size will typically give a good estimate for the total thread stack usage.

It may also be possible to infer a JVM's allocated stack memory by examining the processes memory segments using the methodology of Andrei Pangin's stackmem script. (Noting that this is Linux specific, and that it relies on the JVM requesting individual memory segments from the OS for thread stacks.)

On the other hand, if you wanted to know the amount of stack space currently used (not just allocated), that would be difficult to get from within the application. And if you wanted to get it via an agent, I suspect that you would need to freeze the JVM first. That wouldn't be acceptable for regular monitoring.

But the bottom line is that getting the information will be (at least!) non-trivial and (IMO) probably not worth the effort. There is not a lot that you can do1 with an accurate measure of allocated stack space that you can't already do by looking at thread counts and multiplying ...

... it would be great to monitor this value in runtime.

Not convinced :-)


1 - There are two possible reasons for wanting to know how much stack memory is used: you need to optimize or curiosity. In the former case knowing how much stack memory is used doesn't tell you directly how much ought to be used. To determine the latter, you actually need to determine whether you have too many threads, or if those threads' stacks need to be as big as they currently are. Reducing stack memory usage "on principle" or because some says it is "best practice" could get you into trouble.

Upvotes: 2

ChinmayH
ChinmayH

Reputation: 41

You can try JProfiler. If you want to see it live in action before trying it yourself, check this

Also, your idea that thread stack size varies between 256k and 1m is absolutely correct.

In JDK 8, HotSpot installation comes with a feature named Native Memory Tracking (default: disabled). To enable it, use:

-XX:NativeMemoryTracking=[off|detail|summary]

After enabling NMT, you can examine the memory footprint taken by either Thread or Thread Stack using:

jcmd <pid> VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB]

Upvotes: 3

Related Questions