ThreadMXBean#getThreadAllocatedBytes 会返回分配的内存或对象的大小吗?

tkr*_*man 3 java performance jvm memory-management jmx

我想雇用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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

更新。我试着自己检查:http : //pastebin.com/ECQpz8g4。(sleeps in the code是为了让我用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
Run Code Online (Sandbox Code Playgroud)

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

Nic*_*las 6

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

返回值是一个近似值,因为某些 Java 虚拟机实现可能使用对象分配机制,这会导致分配对象的时间和记录其大小的时间之间存在延迟

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