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

时间:2016-03-23 11:12:58

标签: java performance memory-management jvm jmx

我想雇用 package test.thread; import java.util.List; import java.util.Scanner; public class Producer implements Runnable { private List<String> jobs = null; public Producer(List<String> jobs) { this.jobs = jobs; } @Override public void run() { System.out.println("Starting Producer"); while(true) { synchronized (jobs) { try { if (jobs.isEmpty()) { System.out.println("Please provide the job details: "); Scanner scanner = new Scanner(System.in); String job = scanner.nextLine(); jobs.add(job); scanner.close(); jobs.notifyAll(); Thread.sleep(4000); } else { jobs.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } } } } package test.thread; import java.util.List; public class Consumer implements Runnable { private List<String> jobs = null; public Consumer(List<String> list) { this.jobs = list; } @Override public void run() { while(true) { synchronized (jobs) { try { if (jobs.isEmpty()) { jobs.wait(); } else { for (String job : jobs) { System.out.println("Job completed: " + job); jobs.remove(job); Thread.sleep(2000); } jobs.notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } } } } package test.thread; import java.util.ArrayList; import java.util.List; public class TestThread { public static void main(String...strings ) { List<String> list = new ArrayList<String>(); Producer producer = new Producer(list); Consumer consumer = new Consumer(list); Thread prodThread = new Thread(producer, "producer"); Thread consThread = new Thread(consumer, "consumer"); prodThread.start(); consThread.start(); } } 来做这样的事情:

com.sun.management.ThreadMXBean

问题是,此方法实际返回了什么:在方法调用时分配的新内存量或分配对象的大小?要明确我的意思是什么:

1)假设我在long before = threadMxBean.getThreadAllocatedBytes(currentThreadId); seriousBusiness(); // some calls here long after = threadMxBean.getThreadAllocatedBytes(currentThreadId); long allocDiff = after - before; // use for stats or whatever 调用中分配了一个巨大的数组,因此为此目的分配了一个新的内存区域,seriousBusiness()增加了相应的值。

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

3)我再次做一些调用(在同一个线程中),JVM发现它不需要分配新内存并重新使用该内存区域以达到新的目的,这导致getThreadAllocatedBytes值不增长

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

另外,如果第一个假设是正确的(只是新的内存分配计数),那么进行getThreadAllocatedBytes测量的正确方法是什么?

UPD。我试着检查一下自己:http://pastebin.com/ECQpz8g4。 (在代码中睡觉是为了允许我用JMC连接到JVM)。

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

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

per-thread object allocations / memory footprint

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

2 个答案:

答案 0 :(得分:2)

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

修改

没有&#39;线程所有权&#39; HotSpot JVM中分配的堆内存。分配内存后,它将在所有线程之间共享。所以,&#39;每线程使用&#39;没有意义;当JVM在堆中分配对象时,它不知道此内存是否已在之前和之后使用过。

答案 1 :(得分:2)

引用ThreadMXBean,它代表目标线程报告堆中分配的字节数,但暗示这相当于分配的对象的大小。但有一点需要注意:

  

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

因此,我认为堆空间的回收对报告的值没有影响,因为它只报告分配的绝对字节数,因此如果分配100个字节,则回收80个字节,然后分配另外100个字节,这些事件结束时报告的(delta)值将是200个字节,尽管 net 分配只有120个。