ThreadMXBean#getThreadAllocatedBytes return 分配的内存或对象的大小?

Will ThreadMXBean#getThreadAllocatedBytes return size of allocated memory or objects?

我想雇用 com.sun.management.ThreadMXBean 做这样的事情:

long before = threadMxBean.getThreadAllocatedBytes(currentThreadId);
seriousBusiness(); // some calls here
long after = threadMxBean.getThreadAllocatedBytes(currentThreadId);
long allocDiff = after - before; // use for stats or whatever

问题是,这个方法实际上是什么 return:在方法调用时分配的新内存量 的大小分配对象?要清楚我的意思是什么区别:

1) 假设我在 seriousBusiness() 调用中分配了一个巨大的数组,因此为此分配了一个新的内存区域并且 getThreadAllocatedBytes 增加了相应的值。

2) 一段时间过去了,有一个 GC 运行,那个未使用的数组被收集了,现在内存区域是空闲的。

3) 我再次进行了一些调用(在同一个线程中),JVM 发现它不需要分配新内存并为新目的重用该内存区域,这导致 getThreadAllocatedBytes 值没有增长。

我可能不太清楚 JVM 内存管理是如何工作的,但问题应该很清楚了。

另外,如果第一个假设是正确的(新内存分配算数),那么进行 per-thread object allocations / memory footprint 测量的正确方法是什么?

更新。我试着自己检查一下:http://pastebin.com/ECQpz8g4。 (代码中的休眠是为了让我使用 JMC 连接到 JVM)。

TL;DR:分配一个巨大的 int 数组,然后对其进行 GC,然后分配一些新对象并检查分配的内存。这是我得到的:

所以,看起来 GC 实际上是 运行 并且,虽然内存肯定被分配并随后被释放,但我得到了这个输出:

665328          // before everything started
4295684088      // 4 GiB allocated
4295684296      // did GC (for certain! (really?))
5812441672      // allocated a long string, took new memory

所以,我只是在等待具有 JVM 内存专业知识的人告诉我我是对还是错。

ThreadMXBean.getThreadAllocatedBytes returns 给定线程从一开始分配的堆内存的累积量,即这是一个单调递增的计数器。它大致是分配对象的总大小。

编辑

HotSpot JVM 中没有 'thread ownership' 分配的堆内存。一旦分配了内存,它就会在所有线程之间共享。所以,'per-thread usage' 没有任何意义; JVM在堆中分配对象时,并不知道这块内存之前是否被谁使用过

引用ThreadMXBean,它代表目标线程报告在堆中分配的字节数,但暗示这相当于分配的对象的大小。不过有一个警告:

The returned value is an approximation because some Java virtual machine implementations may use object allocation mechanisms that result in a delay between the time an object is allocated and the time its size is recorded

因此,我假设堆回收 space 对报告的值没有影响,因为它只报告分配的绝对字节数,所以如果你分配 100 个字节,那么 80 个字节是回收,然后再分配 100 字节,这些事件结束时报告的(增量)值将是 200 字节,尽管 net 分配仅为 120.