JVMTI callback SampledObjectAlloc always fires for first allocation in a new thread

Markus Gaisbauer markus.gaisbauer at gmail.com
Fri Jun 5 10:45:12 UTC 2020


Hi,

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.

I am looking for someone who could create a JIRA ticket for this.

Regards,
Markus
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/serviceability-dev/attachments/20200605/604cf6f4/attachment.htm>


More information about the serviceability-dev mailing list