Java内存开销

Java内存开销,java,memory,interface,arraylist,overhead,Java,Memory,Interface,Arraylist,Overhead,我想问一下java中的内存开销, 我有一个很大的ArrayList(61770个条目),并试图计算每个条目占用的内存量(计算对象及其ArrayList条目), 通过对应用程序进行分析,我发现在加载所有数据后,堆需要~25Mb。 当ArrayList只有2个项目时,堆占用~1Mb,因此大致如下: (24*1024*1024)/61768=407字节 然而,当我计算每个对象的字段时,我得到148个字节(不包括ArrayList,假设int=4,float=4,reference=4),我很想知道这些

我想问一下java中的内存开销, 我有一个很大的ArrayList(61770个条目),并试图计算每个条目占用的内存量(计算对象及其ArrayList条目), 通过对应用程序进行分析,我发现在加载所有数据后,堆需要~25Mb。 当ArrayList只有2个项目时,堆占用~1Mb,因此大致如下:

(24*1024*1024)/61768=407字节

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

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

任何帮助都将不胜感激


哇,谢谢你的回答

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

@尤瓦尔A:谢谢你的介绍,这是一个宝贵的信息来源

@Ukko:注意到这一点


@Jayan:现在NetBeans探查器在我尝试转储堆时给了我错误,稍后将重试。

arraylist消耗的内存有点模糊

在完全分配值之后,在适当的阶段对进程进行堆转储。然后使用诸如内存分析器(来自eclipse)之类的工具


您可以找到较浅的和保留的堆大小。

数组列表通常大于元素数。使用
getCapacity()
获取底层数组的当前大小。

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

由于JVM内存开销,单个对象的预期大小大约是预期大小的两倍,这种情况并不少见


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

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

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

  • 启动JVM并进行几次全局GCs以清除所有垃圾
  • 测量堆大小和Java的可用空间概念
  • 运行您的测试
  • 几次
  • 重新进行步骤2的测量

  • 经过所有这些和一点数学,你会更接近,但仍然不正确。唯一真正的解决方案是像其他人提到的那样实际询问实现。或者从实现的知识中找出答案。

    作为旁注,既然您确切知道ArrayList中有多少个对象,为什么不使用数组[]?其中的对象数量会发生变化吗?

    这篇文章可能对您很有用:如果您从新的ArrayList(61770)开始,而不是从新的ArrayList()开始,然后让它自动调整大小,您也会得到不同的开销。在检查内存使用情况之前,您是否设置了正确的大小?@flamealpha:61 770不太大:)我的HashMap太大了,以至于大多数系统都无法使用。。。这就是为什么我用Trove的TIntIntHashMap替换了它们,它的内存/速度效率更高:)唉,它只适用于原语:-/这只是一个例子,要加载的元素的确切数量不是预先确定的,我更关心的是数组指向的对象的内存开销。