【问题标题】:Do arrays of "non-zero" primitives require more memory?“非零”基元数组是否需要更多内存?
【发布时间】:2012-01-19 12:05:53
【问题描述】:

大家好,在编写数组列表实现时,我了解在删除 Item(x) 时将其设置为 null(而不是简单地 quantity -= 1)以防止内存泄漏非常重要。

但是,如果我的数组列表是原始 int 数组列表(由 int[] 支持),将其设置为 0 是否有意义?

类似地,对于原始字符的数组列表(由 char[] 支持),当调用 RemoveRange() 时,用 \u0000 填充该范围是否有意义?还是只更新length 和指针而不修改后备数组完全没问题?

填充零的整数数组可能比填充整数值的等长数组占用的内存更少,因为运行时可以进行优化

【问题讨论】:

  • 如果我没记错的话,这个答案有点不合逻辑。我会让更聪明的人来解释,因为我对这个问题的记忆太模糊了。
  • 很容易错误地确认 int[] 越大,持有的数字越大。有些人根本不知道计算机的工作原理吗?
  • @Ingo 我在想如果它们都是相同的值(即 0)可以进行优化
  • @Pacerier 实际上,在大多数 linux 内核中,calloc 确实优化了这一点,因为它有一个与所有其他页面分开的页面,始终设置为 0。当您第一次尝试写入它时,然后它将您尝试写入的页面更改为内存中新擦除的页面,以节省这些宝贵的资源。但是,我认为 java 中没有类似的东西。
  • 理论上是可能的,我隐约记得有些系统尝试过这种事情。 (当然 APL 会这样做,但它是动态类型的。)但我不认为任何生产 Java 或类 C 的系统会这样做(除了 Richard 提到的 storage swizzle 之类的东西)。

标签: java memory primitive


【解决方案1】:

用零填充的整数数组是否可能比用整数值填充的等长数组占用更少的内存?

假设在这两种情况下我们都在处理int[] - 不。相同类型和相同长度的两个数组将始终占用相同的内存量。

没有需要用 0 覆盖“现在为空”的数组元素。它不会造成任何伤害(除了微小的性能优势),甚至可以在调试时使事情变得更简单,但是你不需要。

【讨论】:

    【解决方案2】:

    ...在编写数组列表实现时,我知道在删除时将Item(x) 设置为null(而不是简单地quantity -= 1)很重要,以防止内存泄漏。

    这不是真的。将变量设置为null 并非总是必要的,不这样做并不意味着您有内存泄漏。

    但是,如果我的数组列表是原始 int 数组列表,将其设置为 0 是否有意义?

    不,对于基元来说,这根本不重要,0 或\u0000(对于字符)只是一个值,就像任何其他值一样。它不会占用更少的空间。

    【讨论】:

    • 如果您要实现类似ArrayList 的类型,这 是必要的。如果我添加一个项目,然后从列表中删除该元素,我不希望该引用无缘无故地在列表中徘徊。
    • 如果您要管理自己的内存,那么您必须管理未使用的无效对象。如果没有,那么如果没有对该对象的进一步引用(在某个未指定的时间),则 GC 会拾取它。
    • @JonSkeet 是的,如果您要实现自己的 List,这可能是个好主意。尽管许多人认为将变量设置为 null 通常是一个好主意(不了解确切原因)。在我看来,你不应该仅仅因为你对它“好”有一个模糊的想法就去做——只有在你明白为什么的情况下才去做。
    • @Jesper:是的 - 但在这种情况下,问题确实说明上下文。
    【解决方案3】:

    不,没有必要对原始类型执行此操作(即将它们设置为 0),因为“插槽”被显式取消的唯一原因是为了防止对它们的虚假引用,从而搞砸垃圾收集。

    【讨论】:

      【解决方案4】:

      您不能拥有ArrayList<int> 或任何其他具有原语的容器类。关于普通数组,请参阅 Jon Skeets 的回答。

      【讨论】:

      • 我很确定他知道这一点并想创建自己的非泛型 ArrayList 类,例如 IntArrayList
      • +Sanjay - 我不太确定。无论如何,我不应该回答某人可能的意思,而是回答他确实问过的问题。
      • 我在他实现自己的数组列表(不使用 ArrayList)时阅读它。
      • @wmorrison365 是的,你是对的,我说的是原始整数的数组列表,而不是 java.util.ArrayList
      【解决方案5】:

      不,您需要使数组中的对象槽无效以防止泄漏。如果该对象仍被您的数组引用,则它不能被 GC'd - 所以您引用的泄漏。

      另一方面,原语无论如何都是在堆栈上分配的,而不是在堆上,所以无论如何都不会被 GC。作为类的实例变量的原语被存储为相关对象的字段,并在对象被 GC 时清理。

      此外,JLS 表明原语的大小是特定于 VM 的,但大多数(全部?)VM 当前支持 4 字节整数。请参阅JLS 了解更多信息:

      【讨论】:

        【解决方案6】:

        基元和引用总是占据相同的空间。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-07-06
          • 2014-07-16
          • 1970-01-01
          • 1970-01-01
          • 2012-02-08
          • 1970-01-01
          • 2013-01-16
          • 2015-03-01
          相关资源
          最近更新 更多