Java内存开销

时间:2010-04-27 12:50:01

标签: java memory interface arraylist overhead

我想问一下java中的Memory Overhead, 我有一个大型ArrayList(61,770项),并尝试计算每个项目所占用的内存量(计算对象及其ArrayList条目), 通过分析应用程序,我得到所有数据加载后,堆需要〜25Mb。 当ArrayList只有2个项时,堆需要〜1Mb,所以粗略地说:

(24 * 1024 * 1024)/ 61,768 = 407字节。

然而,当我计算每个对象的字段时,我得到148个字节(不包括ArrayList,假设int = 4,float = 4,reference = 4),我很好奇知道所有这些额外字节来自哪里......

我可以猜测,因为我存储在ArrayList中的对象正在实现一个接口,它们存储了额外的值,也许VM为每个实现的方法存储了一个4byte的函数指针? 它们实现的接口有20个函数,因此80个字节,总共228个字节,仍然不接近测量的400个字节。

任何帮助将不胜感激。


哇,谢谢你所有的好答案。

@Bolo:感谢链接,这个类我测量每个对象大约350个字节,所以我至少可以确认大内存使用的来源。

@Yuval A:谢谢你的介绍,这是一个宝贵的信息来源。

@Ukko:指出。

@Jayan:现在NetBeans Profiler在我尝试转储堆时给出错误,稍后再试。

5 个答案:

答案 0 :(得分:6)

这些结果并不令人惊讶。 JVM为每个对象增加了大量开销。

由于JVM内存开销,单个对象的预期大小增加一倍并不罕见。

This presentation对Java中各种数据结构内存使用情况进行了精彩,深入的解释和概述。

答案 1 :(得分:2)

ArrayList通常大于元素数量。使用getCapacity()获取基础数组的当前大小。

答案 2 :(得分:2)

您的方法的一个大问题是与垃圾收集器的交互。它基本上使你所提出的任何测试从外部完全不透明。

作为一个思想实验,如果你想这样做,你应该

  1. 启动你的JVM并做几个全球GC以获得所有垃圾
  2. 测量堆大小和Java关于它有多少可用空间的概念。
  3. 运行测试
  4. GC几次
  5. 重做步骤#2的测量值
  6. 经过所有这些以及一些数学运算,你会更接近但仍然不对。唯一真正的解决方案是像其他人提到的那样实际问问实施。或者从实施的知识中弄清楚。

答案 3 :(得分:1)

arraylist消耗的内存有点模糊。

在完全分配值后,在适当的阶段获取进程的堆转储。然后使用内存分析器等工具(来自eclipse)。

您填写查找浅层和保留堆大小。

答案 4 :(得分:0)

作为旁注,由于您确切知道ArrayList中有多少个对象,为什么不使用数组[]?那里的对象数量会改变吗?