如何测量java方法的内存使用情况



听起来很奇怪,但仍然如此。

想象一下我有一个java方法

boolean myMethod(Object param1, Object param2) { 
   // here can be some simple calculations. can be some services invokation
   // or calls to DB. doesn't matter
  return someValue;
}

如何测量JVM执行此方法所使用的内存量?实际有多少内存使用此方法执行?

有什么工具吗?或者我可以在我的方法中添加一些额外的代码,以便查看使用过的内存?

我使用JConsole来监视JVM,我也知道我们可以使用java.lang.Runtime来查看freeMemory,但实际上我不知道我的方法使用这些工具使用了多少内存。

测量方法每次调用的真实大小并不像听起来那么简单,JVM也不支持它。复杂性产生于a)因为JVM是为了隐藏这种低级别的细节而设计的,b)JVM在任何时候都可能有同一方法的多个变体,这听起来很疯狂,但也是真的。有时,该方法会被内联,或进行更大程度的优化,甚至以一种特殊的方式重新编译,以支持该方法在运行时的热交换(!),这可能会从根本上改变其运行时大小。

测量方法调用使用的堆数量

假设方法调用不使用堆,那么很容易说0字节。但是,可能需要知道由方法调用分配的任何新对象的大小。这是可以回答的,但是对象是在方法调用和线程之间共享的。因此,人们必须非常清楚他们想要测量什么,并注意不要重复计算。Java中有一些库会给出对象的大小,它们通常通过反射和启发式来工作,或者它们包装sun.msic.Unsafe来检查指向对象及其数据的指针。例如http://code.google.com/p/javabi-sizeof/.

测量方法的分配率

YourKit有一个很好的工具,可以跟踪源点的每个对象分配,并报告它们的总大小和速率。这对于找出GC流失的原因非常有用。

测量每个方法调用使用的堆栈数量

JVM不发布此信息,如前所述,它将根据当前活动的优化和使用的运行时编译器而有所不同。

另一种选择是使用启发式方法。类似于计算方法中使用了多少变量,然后将计数乘以4,以字节为单位给出答案(假设每个变量的大小为4字节,即int)。显然,这种启发式方法是有缺陷的,可以改进,但它足够简单,可以给出一个快速且具有代表性的答案。

我过去使用过以下内容,我发现它很有用:

http://www.javamex.com/classmexer/

最新更新