占用最少内存的Java对象

时间:2012-08-26 19:00:52

标签: java performance memory collections

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

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

5 个答案:

答案 0 :(得分:5)

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

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

除了

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

答案 1 :(得分:5)

如果您需要由Set<K>支持的ConcurrentHashMap,则应使用Collections.newSetFromMap,例如

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

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

编辑:实际上,在这里分配一个特定的对象作为你的值将比使用一个可能被分配的预先存在的对象占用更多的内存。您可以使用对在VM初始化期间或多或少始终分配的对象的引用,例如Object.class。我真的建议你只使用第一个解决方案。

答案 2 :(得分:2)

对象的大小包括:

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

例如(假设是32位JVM):

public MyBoolObject {
  boolean flag;
}

将占用16 bytes8bytes(标题)+ 1byte(实例变量)+ 7bytes(填充)。
由于您对地图值不感兴趣,因此可以将它们设置为null。这会从堆栈中消耗48个字节的内存(32/64位)。

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

答案 3 :(得分:0)

原始数据类型不是对象。

因为java中的所有对象都必须从超类Object继承。然后,java中最小的可想到的对象将是您定义的没有成员的类。这样的课程将毫无用处。

答案 4 :(得分:0)

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