2016-11-14 69 views
1

我想知道是否有任何轻量级的方法来(粗略地)测量一个给定的Java类正在使用多少内存。让我们考虑以下接口:监视Java对象在特定方法中的分配/释放

interface MyAction <T, R> { 
    R execute(T item); 
} 

我想知道有多少内存作为实例字段中的所有对象或作为overrided执行方法变量使用。当然,它也应该考虑调用其他方法时创建的每个对象。 至于我能理解(阅读本reply)最好的办法是:

  • 补丁JVM字节码通过ASM框架和地方钩之前的任何下列指令:新,newarray,anewarray,multianewarray。

  • 通过更改JNI函数表来拦截所有的JNI调用(如果有的话)。

  • 拦截所有VMObjectAlloc事件。

这3个步骤将涵盖每一个可能的分配,但我无法弄清楚是否有任何好的方法来跟踪对象的重新分配。

我会修补finalize方法字节码,以便获得有关对象gc释放和拦截所有ObjectFree事件(仅用于标记对象)的通知。我确信这不会涵盖所有的释放事件,因此我想知道是否有一些已知的技术(我无法找到)可以帮助我解决这个问题。

预先感谢您。

+1

只是想知道:为什么你想知道这一切? – GhostCat

+0

如果您想进行一些手动分析,您可以创建一个堆转储并使用Eclipse MAT等工具对其进行分析。除此之外,解除分配应该可以通过'finalize()'来跟踪,但是由于vm不能保证不需要的对象永远不会被终结,我不会指望这一点。实际上,你可以将任何不能从活动线程访问的对象作为垃圾收集/解除分配的可用对象,但在运行时分析它可能会花费相当多的成本,而现有的堆转储分析器将完全适合您。 – Thomas

+0

说实话,我想在运行时知道这样的信息,因为我试图优化一个已经拥有自己的内存管理系统来进行内部处理。由于代码无法控制MyAction,所以根据实时统计进行即时调整有望导致更好的内存管理器。当然,我仍然在评估游戏是否值得这一点。 @Thomas是的,肯定finalize()是不值得信任的。 –

回答

0

由于您对分配的内存量感兴趣,而不是每个单独分配的对象,因此可以使用更简单的方法。

有一种方法ThreadMXBean.getThreadAllocatedBytes,它返回给定线程分配的累积内存量。在拨打execute之前和之后,您只需要记录计数器。差异将是该方法分配的估计总内存(考虑到它不跨越多个线程)。

这里是如何得到的com.sun.management.ThreadMXBean实例:

com.sun.management.ThreadMXBean mxBean = 
      (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean(); 

有作为Java对象释放没有这样的事件。完全GC之前,您无法找到对象是否可到达。即使GC不“解除分配”对象 - 它通常只是穿过活动对象,并将其他一切视为自由空间。

如果您需要在调用方法后查找Java堆的更改方式,则可以在调用之前和之后创建堆快照。

+0

谢谢您的回复。不幸的是,这不是我的情况,因为我需要在执行我的方法期间监视分配情况。此外,我不能只为该方法调用专用的线程。这个想法是根据execute()方法中的内存消耗调整系统中使用的java.nio.ByteBuffer的数量。然而,只要有可能进行每个线程堆转储,我认为这是不可行的,那么关于堆快照的想法可能会很有趣。 –