Java内存开销

4
我想询问Java中的内存开销问题,我有一个大ArrayList(61,770项),正在尝试计算每个项占用的内存量(计算对象及其ArrayList条目),通过对应用程序进行分析,我得知在所有数据加载完成后,堆占用了大约25Mb。当ArrayList仅具有2个项目时,堆使用了大约1Mb,因此大致可以得出:
(24*1024*1024)/61,768 = 407字节。
然而,当我计算每个对象的字段时,我得到148个字节(不包括ArrayList,并假设int=4,float=4,reference=4),我很好奇那些额外的字节来自哪里...
我猜测,由于我存储在ArrayList中的对象正在实现接口,它们存储额外的值,也许VM为每个已实现方法存储4字节的函数指针?它们实现的接口有20个函数,因此还需要80个字节,总共为228个字节,仍然与测量的400个字节不接近。
如果有帮助将不胜感激。
哇,谢谢您所有的回答。
@Bolo: 感谢您提供的链接,使用这个类我测量每个对象的大小约为350个字节,因此我至少可以确认大量内存使用的来源。
@Yuval A: 谢谢您提供的演示文稿,这是有价值的信息来源。
@Ukko: 注意到了。
@Jayan: 现在NetBeans分析器在尝试转储堆时出现错误,稍后再试。

3
这篇文章可能对你有用:http://www.javaworld.com/javaworld/javatips/jw-javatip130.html - Bolo
如果你使用new ArrayList(61770)而不是例如new ArrayList(),然后让它自动调整大小,你也会得到不同的开销。在检查内存使用之前,你是否设置了正确的大小? - extraneon
@flamealpha:61 770并不算大:) 我有一个HashMap<Integer,Integer>,它非常大,以至于它们会让大多数系统崩溃...这就是为什么我用Trove的TIntIntHashMap替换它们,因为它们在内存/速度效率方面更加高效:) 可惜,它只适用于原始数据类型 :-/ - SyntaxT3rr0r
5个回答

6

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

由于JVM内存开销,单个对象的预期大小约为实际大小的两倍,并不罕见。

这篇演示文稿对Java中各种数据结构的内存使用情况进行了深入而全面的解释和概述。


2

ArrayList通常比元素数量大。使用getCapacity()获取底层数组的当前大小。


2
你的方法中存在一个重大问题,与垃圾收集器交互会使得像你所提出的测试变得完全不透明。作为思想实验,如果你想这样做,你应该:
  1. 启动JVM并进行几次全局GC以清除所有垃圾
  2. 测量堆大小和Java关于剩余空间的概念
  3. 运行你的测试
  4. 再进行几次GC
  5. 重新执行第2步中的测量
在完成所有这些操作并经过一番计算后,你会更接近答案,但仍然不够准确。唯一真正的解决办法是向实现者询问,就像其他人所提到的一样,或从对实现的了解中找到答案。

1

ArrayList所消耗的内存有点模糊。

在适当的阶段对进程进行堆转储 - 在值完全分配后。然后使用像内存分析器(来自Eclipse)这样的工具。

您将找到浅层堆和保留堆大小。


0

顺便提一下,既然您知道ArrayList中会有多少个对象,为什么不直接使用数组[]呢?里面的对象数量会改变吗?


这只是一个案例示例,要加载的元素数量并没有预先确定,我更关心的是数组指向的对象的内存开销。 - user326841

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