为什么创建一个大型Javaarrays会占用如此多的内存?

为什么以下行

Object[] objects = new Object[10000000]; 

导致JVM使用大量内存(~40M)? 有什么方法可以在分配数组时了解VM的内部工作原理吗?

好吧,它为10000000个引用分配了足够的空间,以及数组对象本身的少量开销。

实际大小将取决于VM – 但它占用相当大的内存肯定不足为奇……我希望64位VM上至少有 40MB,可能是80MB,除非它使用压缩oopsarrays。

当然,如果使用那么多不同的对象填充数组,那将占用更多,更多的内存……但是数组本身仍然只需要用于引用的空间。

“很多记忆”是什么意思? 你分配10000000个指针,每个指针占用4个字节(在32位机器上) – 这大约是40mb的内存。

您正在创建一千万个对象的引用。 引用至少为4个字节; Java中的IIRC可能是8,但我不确定。

因此,使用这一行,您将创建40或80兆字节的数据。

您正在为一千万个参考预留空间。 那是相当多的。

它导致使用大量内存,因为它需要为1000万个对象分配堆空间及其相关的开销。

要查看JVM的内部工作原理,您可以查看其源代码 ,因为它是开源的。

你的数组必须容纳1000万个对象引用,在现代平台上是64位(8字节)指针。 由于它被分配为一个连续的存储块,因此它应该需要8000万字节。 从某种意义上讲,这是很大的,与你可能拥有的内存量相比很小。 为什么打扰你?

它创建一个包含10.000.000个引用指针的数组,所有引用都用null初始化。

你有什么期望,说这是“很多”?


进一步阅读

  • Java中对象引用的大小

arrays使用如此广泛的一个主要原因是它们的元素可以在恒定时间内访问。 这意味着访问[i]所花费的时间对于每个索引i是相同的。 这是因为可以通过向arrays头部的地址添加合适的偏移来算术地确定a [i]的地址。 原因是数组内容的空间被分配为连续的内存块。

根据这个站点,数组的内存使用量是一个12字节的头文件+每个元素4个字节。 如果声明一个包含10M元素的空数组,那么从一开始就使用大约40MB的内存。 如果你开始用实际的10M对象填充该数组,那么大小会非常快速地增加。

从这个站点,我刚刚在我的64位机器上测试它,普通Object的大小大约是31个字节,所以一个10M的Object数组大约是12个字节+(4 + 31个字节)* 10M = 350 000 012字节(或345.78 MB)

如果您的数组持有其他类型的对象,则大小将更大。

如果你必须在你的程序中保留这么多数据,我建议你使用某种随机存取文件来保存数据。 甚至可以使用Apache Derby等数据库,这也可以让您对数据进行排序和过滤等。

我可能落后于时代,但我从“实用Java”一书中了解到,矢量比数组更有效,更快。 是否可以使用Vector而不是数组?