Mark Bramnik
Mark Bramnik

Reputation: 42441

JVM getting allocation call stacks programmatically

This is a follow-up question to this one

So I keep exploring modern profilers capabilities from the "programmatic access" standpoint, and I came across something beyond my understanding.

This time I've stumbled upon The "Allocation Call Tree" feature in JProfiler:

Allocation Call Tree

I do see that in order to get this kind of information, I have to trigger the sampled allocation with a rate of 1/10 by default and then specify (preferably) the package in which the allocated classed will be recorded.

Step 1

Step 1

Step 2

Step 2

But then I don't really understand how can the information about the call-stacks be "matched" with the information about the allocated objects.

Of course my question is not about the implementation details of JProfiler, I understand its a commercial tool with a close code and everything, but rather about the general understanding of how can this kind of information can be retrieved.

My initial guess is that it somehow "instruments" the already-loaded class files to "intercept" each and every allocation for these objects (with a sampling rate to not slow down the process too much) but then what? Does it call something like Thread.currentThread().getStackTrace() and records the actual stack trace that has led to the allocation?

On the other hand, its activated in the "sampling mode" (as opposed to the instrumentation) + there is a performance concern - this sounds a really expensive thing to do (read, should not be used in production) to me, but I might be wrong, so any advice will be appreciated.

Upvotes: 3

Views: 244

Answers (1)

Ingo Kegel
Ingo Kegel

Reputation: 47975

My initial guess is that it somehow "instruments" the already-loaded class files to "intercept" each and every allocation for these objects

Since Java 11 delivered JEP 331 it uses these capabilities in the native JVMTI in order to sample allocations. Before Java 11, it instruments the java.lang.Object constructor. As for the call stacks, it depends on whether instrumentation or sampling is used. For instrumentation, it uses the call stack that is already built by the instrumentation. For sampling, the call stack built by sampling is not precise enough, so it queries the call stack through JVMTI.

Does it call something like Thread.currentThread().getStackTrace()

For sampling it's a bit like that, but doing it in Java would create a huge overhead because of the many secondary allocations. JVMTI is a native interface and can do this more efficiently.

Upvotes: 3

Related Questions