【问题标题】:Java object which takes the least memory占用内存最少的 Java 对象
【发布时间】:2012-08-26 19:00:52
【问题描述】:

这是一个愚蠢的问题,但在这里。

我有一个多线程程序和一个独特元素的“全局”集合。由于性能,我拒绝了 ConcurrentHashMap 的同步 Set 实现。我真的不需要 Map 的 Value 部分,所以我想在内存使用方面使用 java 中最小的 Object。我以不同的方式解决了这个问题(在 Map 中多次引用单个布尔对象),但我仍然很好奇 Java 中最小的对象是什么。我一直认为它是布尔值,但我认为这不是真的 (Java - boolean primitive type - size, Primitive Data Types)

【问题讨论】:

  • 原始类型与对象不同。 Boolean 是不可变的包装对象,boolean 是原始类型。
  • 如果你真的想要Set<K>,你可以使用Collections.setFromMap(new ConcurrentHashMap<K, Boolean>())。这为你做你的工作:-)
  • 如果你真的想要最小的对象,我可能只使用 Object... 因为它是所有其他 Object... 的基类 :-)跨度>

标签: java performance memory collections


【解决方案1】:

实际上,这并不重要,因为每个关联的值部分都固定为引用。您甚至可以在这里使用null 作为值,但任何其他(固定)对象引用应该没问题(有时更方便)。我更喜欢Boolean.TRUE(或类似的“知名”单身人士)。然后,您可以通过

测试成员资格
if (myMap.get(someKey) != null) { ... }

除了

if (myMap.containsKey(someKey)) { ... }

【讨论】:

  • 好的,但是你不能真正检查密钥是否存在(除非 -> KeySet.iterator)。因此需要一个能够执行此检查的值。还是我错过了什么?
  • @alien01 Map.keySet().contains()
  • @alien 查看编辑。特别是,containsKey 在地图上始终可用。
  • @Dirk 在没有关联值的情况下使用myMap.get(someKey)(即get 返回null)将在尝试自动拆箱时导致NullPointerException
【解决方案2】:

如果你想要一个由ConcurrentHashMap 支持的Set<K>,你应该使用Collections.newSetFromMap,例如

final Set<K> set = Collections.newSetFromMap(new ConcurrentHashMap<K, Boolean>());

现在,如果您真的想重新发明轮子,并且非常关心 内存使用情况,我建议您只使用简单的 Object 作为您的值。由于 Java 中的每个对象都继承自 Object(通用基类),内存中任何对象的大小都必须大于或等于普通 Object 的大小。您不能使用原语,因为泛型类型参数必须是 Objects。

编辑:实际上,在此处分配特定对象用作您的值将比使用可能会分配给任何情况的预先存在的对象占用更多内存。您可以只使用对在 VM 初始化期间或多或少始终分配的对象的引用,例如Object.class。不过,我真的建议您只使用第一种解决方案。

【讨论】:

    【解决方案3】:

    一个对象的大小包括:

    • 它持有的实例变量的大小
    • 一个 8 或 16 字节的标头(取决于 Hotspot VM(32/64 位))
    • 填充:其大小始终填充为 8 字节的倍数。

    例如(假设是 32 位 JVM):

    public MyBoolObject {
      boolean flag;
    }
    

    将占用16 bytes: 8bytes(header) + 1byte(instance variable) + 7bytes(padding)。
    由于您对地图值不感兴趣,因此可以将它们设置为 null。这会消耗堆栈中的48 字节内存(32/64 位)。

    您还可以查看这个关于众所周知的 Java 数据结构的成本/元素的好列表: http://code.google.com/p/memory-measurer/wiki/ElementCostInDataStructures

    【讨论】:

      【解决方案4】:

      原始数据类型不是对象。

      由于java中的所有对象都必须继承自超类Object。那么Java中最小的可以想象的对象将是您定义的没有成员的类。这样的类将毫无用处。

      【讨论】:

        【解决方案5】:

        Object 类是可实例化的,它的实例绝对是 Java 中最小的对象。但是,许多其他对象具有完全相同的占用空间,IntegerBoolean 是 64 位 VM 上的示例。这是由于堆内存对齐造成的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-03
          • 1970-01-01
          • 2011-02-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多