Copied over from https://mail.openjdk.java.net/pipermail/serviceability-dev/2020-June/031758.html JVMTI callback SampledObjectAlloc is currently always called for the first allocation of a thread. This generates a lot of bias in an application that regularly starts new threads. I tested this with latest Java 11 and Java 15. E.g. here is a sample that creates 100 threads and allocates one object in each thread. public class AllocationProfilingBiasReproducer { public static void main(String[] args) throws Exception { for (int i = 0; i < 100; i++) { new Thread(new Task(), "Task " + i).start(); Thread.sleep(1); } Thread.sleep(1000); } private static class Task implements Runnable { @Override public void run() { new A(); } } private static class A { } } I built a simple JVMTI agent that registers SampledObjectAlloc callback and sets interval to 1 MB with SetHeapSamplingInterval. The callback simply logs thread name and class name of allocated object. I see the following output: SampledObjectAlloc Ljava/lang/String; via Task 0 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 1 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 2 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 3 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 4 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 5 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 6 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 7 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 8 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 9 SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 10 ... This is not expected. I set a breakpoint in my SampledObjectAlloc callback and observed the following: In MemAllocator::Allocation::notify_allocation_jvmti_sampler() the local var bytes_since_last is always 0xf1f1f1f1f1f1f1f1 for first allocation of a thread. So first allocation is always reported to my agent. ThreadLocalAllocBuffer::_bytes_since_last_sample_point does not seem to be explicitly initialized before accessing it for the first time. I assume 0xf1f1f1f1f1f1f1f1 is a default value provided by some Hotspot allocator. Only after the first event fired, notify_allocation_jvmti_sampler calls ThreadLocalAllocBuffer::set_sample_end which initializes _bytes_since_last_sample_point to a proper value.
|