我想问一下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在我尝试转储堆时给出错误,稍后再试。
答案 0 :(得分:6)
这些结果并不令人惊讶。 JVM为每个对象增加了大量开销。
由于JVM内存开销,单个对象的预期大小增加一倍并不罕见。
This presentation对Java中各种数据结构内存使用情况进行了精彩,深入的解释和概述。
答案 1 :(得分:2)
ArrayList通常大于元素数量。使用getCapacity()
获取基础数组的当前大小。
答案 2 :(得分:2)
您的方法的一个大问题是与垃圾收集器的交互。它基本上使你所提出的任何测试从外部完全不透明。
作为一个思想实验,如果你想这样做,你应该
经过所有这些以及一些数学运算,你会更接近但仍然不对。唯一真正的解决方案是像其他人提到的那样实际问问实施。或者从实施的知识中弄清楚。
答案 3 :(得分:1)
arraylist消耗的内存有点模糊。
在完全分配值后,在适当的阶段获取进程的堆转储。然后使用内存分析器等工具(来自eclipse)。
您填写查找浅层和保留堆大小。
答案 4 :(得分:0)
作为旁注,由于您确切知道ArrayList中有多少个对象,为什么不使用数组[]?那里的对象数量会改变吗?