【问题标题】:Why does creating a big Java array consume so much memory?为什么创建一个大的 Java 数组会消耗这么多内存?
【发布时间】:2011-04-12 18:03:04
【问题描述】:

为什么下面一行

    Object[] objects = new Object[10000000];

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

【问题讨论】:

  • 内存是多少?您预计会消耗多少?
  • @Malcolm:很好的问题。这些天来,我们不认为 40MB 就是那么多内存,是吗?然而,回到过去......
  • 嗯,刚刚在答案中说过,如果它是 40 MB,它还不算“太多”,对于如此大长度的引用数组来说,这是一个正常的数量。但如果是数倍以上,那将是一个完全不同的问题。
  • 真正的问题不是“它是不是太大了”,而是“它做它做的事情是否有用”,在实现一些你不能用这么大的程序功能方面大批?总的来说,我怀疑这么大的数组的实用性,尤其是指向对象的指针。
  • 但是你下次可以用更外交的方式说出来;-)

标签: java arrays memory


【解决方案1】:

嗯,这为 10000000 个引用分配了足够的空间,并为数组对象本身分配了少量开销。

实际大小将取决于虚拟机 - 但它占用相当多的内存肯定不足为奇...我希望 至少 40MB,在 64 上可能是 80MB -bit VM,除非它使用compressed oops 来表示数组。

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

【讨论】:

【解决方案2】:

我可能落后于时代,但我从《实用 Java》一书中了解到,向量比数组更高效、更快。可以用 Vector 代替数组吗?

【讨论】:

  • 使用向量不会减少它的资源。事实上,它可能更糟糕,因为 Vector 在内部使用数组,并且随着插入更多项目 + 1 个元素调整数组的大小:)
  • 非常有趣 - 不知道。谢谢!
  • 关于 Java 中对象内存的一个很好的讨论(同意你的评估,Yanick)javaspecialists.eu/archive/Issue029.html
  • 你不能说向量总是更有效——这取决于它们的使用方式。向量(更好:列表 - 使用界面)更容易使用(可调整大小,您可以在任何地方插入等),因此它们通常是首选。
【解决方案3】:

根据this 站点,数组的内存使用量是 12 字节标题 + 每个元素 4 字节。如果您声明一个包含 10M 元素的 Object 的空数组,那么您从一开始就只使用了大约 40MB 的内存。如果你开始用实际 10M 的对象填充该数组,那么大小会迅速增加。

来自this 站点,我刚刚在我的 64 位机器上对其进行了测试,普通的 Object 的大小约为 31 个字节,因此 Object 的 10M 数组仅约为 12 个字节 + ( 4 + 31 字节)* 10M = 350 000 012 字节(或 345.78 MB)

如果你的数组存放的是其他类型的对象,那么大小会更大。

如果您必须在程序中保留如此多的数据,我建议您使用某种随机访问文件来保存您的数据。甚至可以使用Apache Derby 之类的数据库,它还可以让您对数据进行排序和过滤等。

【讨论】:

  • 为什么是“4*31”而不是“4+31”?
  • 哎呀,是的,它已修复。谢谢:)
【解决方案4】:

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

【讨论】:

  • 是的...你好,基础数学!它占用了应有的确切内存量。
【解决方案5】:

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

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


进一步阅读

【讨论】:

    【解决方案6】:

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

    【讨论】:

      【解决方案7】:

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

      要查看 JVM 的内部工作原理,您可以check out its source code,因为它是开源的。

      【讨论】:

      • 堆空间没有分配,而对象不是使用new创建的,不是吗?
      • 这是查看它的一般方式,因为要创建一个对象,您使用new,然后它会进入堆。但更具体地说:堆包含对象及其实例变量(包括不是用new 创建的原语)。数组值也在堆上。
      • @Manuel Selva:是的,数组中 contained 对象的堆空间仅在您创建对象时分配。然而,数组本身也需要空间来保存对象引用,如其他答案中所述。数组的空间被立即分配,即使它只包含空值。
      【解决方案8】:

      您正在为一千万个引用保留空间。这是相当多的。

      【讨论】:

        【解决方案9】:

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

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

        【讨论】:

          【解决方案10】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-09-30
            • 2018-10-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-09
            • 1970-01-01
            相关资源
            最近更新 更多