ThreadMXBean.getThreadAllocatedBytes() allocates memory
David Holmes
david.holmes at oracle.com
Sun Sep 18 23:45:40 UTC 2016
Hi Bengt,
On 19/09/2016 7:14 AM, Bengt Rutisson wrote:
>
> Hi Serviceability,
>
> Not sure, but I hope this is the correct list to post this on.
Sure is.
> I wanted to use the ThreadMXBean.getThreadAllocatedBytes() method to get
> some information about how much memory some Java code allocated.
>
> When I dug into the results they didn't properly add up until I realized
> that the call to getThreadAllocatedBytes() actually allocates memory.
> This was a surprise to me.
>
> I'm attaching a small example to illustrate what I mean.
>
> Running the example renders this output:
>
> $ javac AllocMeasure.java
> $ java AllocMeasure
> Bytes allocated: 48
> Bytes allocated: 48
> Bytes allocated: 48
> Bytes allocated: 48
> Bytes allocated: 48
> Bytes allocated: 48
> Bytes allocated: 48
> Bytes allocated: 48
> Bytes allocated: 48
> Bytes allocated: 48
>
> What I would have expected was that it would say "Bytes allocated: 0"
> since I would like to add my own code between line 9 and 10 in the
> example and get the value for how much memory it allocates. As it is now
> I have to deduct the bytes that the getThreadAllocatedBytes() allocates
> to get the correct result.
>
> The problem is that getThreadAllocatedBytes() is implemented this way:
>
> public long getThreadAllocatedBytes(long id) {
> long[] ids = new long[1];
> ids[0] = id;
> final long[] sizes = getThreadAllocatedBytes(ids);
> return sizes[0];
> }
>
> http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/32d957185656/src/java.management/share/classes/sun/management/ThreadImpl.java#l345
>
> I was surprised to see the "new long[1]". I realize that it is nice to
> reuse getThreadAllocatedBytes(long []) method, but maybe a pre-allocated
> array can be used instead of allocating a new one for each call?
Did you also notice this code:
protected long[] getThreadAllocatedBytes(long[] ids) {
boolean verified = verifyThreadAllocatedMemory(ids);
long[] sizes = new long[ids.length];
so we're allocating another array for the return value(s).
Bit difficult to use a pre-allocated array - when would you allocate it?
when would you release it? Would you have one per-thread or a freelist
of them? It all gets a bit too hard to manage.
A better API would allow the user to pass in the result array as well -
to allow for array allocation and reuse outside of the region of code
that is being measured.
> I know the specification for this method is kind of fuzzy, but is this
> to be considered a bug or does it work as intended?
I'd call it a quality of implementation issue. It would be better if the
allocation could be avoided, but that requires two entry points to the
VM code. Certainly the query for a single thread should avoid the need
for any array allocation. But I think this pattern is common throughout
the management code.
You should a file a RFE for 10.
Cheers,
David
> Thanks,
> Bengt
More information about the serviceability-dev
mailing list