我该如何估算一个类的总PermGen内存消耗?

12

最近我在写一个类时发现,通过增加代码复杂性可以减少实例内存消耗约10个字节/元素,但代价是增加编译的.class文件大小约10KB。

我假设JVM必须将.class文件加载到内存中,因此除非有至少1000个元素左右,否则这些更改不会回报成本。但是,除非额外的10KB在类文件中是增加代码复杂性的唯一代价,否则这种算法行不通。

这篇Oracle博客指出,在永久区中,类所消耗的额外内存并不仅仅基于.class文件——例如,我怀疑更复杂的代码可能需要更多内存来存储优化元数据。

因此,这个问题有两个部分:

  • 我该如何测量特定类的永久区实际内存消耗?无论是运行时使用一些工具进行检测,还是使用分析工具?
  • 在编写过程中是否有一种方法可以估计类的永久区内存消耗?(使用某些背景知识,您可以在编写实例时估计内存消耗;我想知道是否可以估计类本身在永久区中的内存消耗。)

欢迎提供Dalvik VM的类似细节,但我主要关注OpenJDK和其他“主流”JVM。


内存需求也取决于HotSpot是否编译它。 JIT编译的代码有其自身的成本。 - Jesse Wilson
@JesseWilson:这显然是正确的,但有没有好的方法来估计这个成本?仅仅是原始汇编代码的消耗,还是有很多额外的簿记工作? - Louis Wasserman
我可能会说些奇怪的话,但由于XXX.class是Class的一个实例,我们不能使用与普通实例相同的方法吗?比如Java代理的getObjectSize方法?但也许它不包括你所谈论的“优化元数据”。 - Sebastien Lorber
2个回答

4
如何测量特定类的实际permgen内存消耗?可以在运行时使用一些仪器或者使用性能分析工具吗?
一种方法是在不同的类加载器中加载要衡量的类,然后使用“jmap -permstat”命令,如此博客文章所述。
对于每个类加载器对象,打印以下细节:
  1. 类加载器对象的地址 - 在运行该实用程序时进行快照。
  2. 使用方法(java.lang.ClassLoader.defineClass)定义的由此加载器加载的类的数量。
  3. 所有由该类加载器加载的类的元数据消耗的大约字节数。
  4. 父类加载器的地址(如果有)。
  5. “活”或“死”的指示 - 指示加载器对象是否将来会被垃圾回收。
  6. 此类加载器的类名称。

哦哦哦。我会调查这个。 - Louis Wasserman
@LouisWasserman - 你调查后有更多的信息吗? - dimo414

0
这是对你第二点的回答;我不确定这有多有用,但我发现构建内存高效的Java应用程序:实践和挑战中的幻灯片在估计各种Java对象的大小和健康状况方面非常有帮助。他详细介绍了在32位和64位JVM中估算对象大小的方法,并提供了使对象更加内存高效的指针。

确实,那个演示激励我尝试编写更复杂但每个元素内存效率更高的实现,但现在我在想我是否实际上让问题变得更糟了。 ;) - Louis Wasserman
@LouisWasserman 不一定更糟,但可能会更加复杂。 :) - Vivin Paliath
好吧...如果内存中的实例从未超过1000个元素,那么看起来情况可能确实更糟。 - Louis Wasserman
@LouisWasserman 我以为你在谈论你的代码!但是,我同意。 - Vivin Paliath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接