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.
我想雇用 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,然后分配一些新对象并检查分配的内存。这是我得到的:
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.