哈希映射内存开销

我正在研究哈希地图的内部结构,我遇到了以下细节:

  • 实现是一个HashMap $ Entry对象的数组:

  • 每个HashMap $ Entry包含: – int KeyHash – Object next – Object key – Object Value

  • 默认容量为16个条目

  • 空大小为128个字节

  • HashMap的开销是48个字节,对于数组加上(16 +(条目* 4个字节)) – HashMap $ Entry对象的开销

  • 每个键的额外32字节↔值输入HashMap的开销是
    因此: – 48个字节,每个条目加36个字节

任何人都可以解释我“HashMap的开销是48字节,加上(16 +(条目* 4字节))数组”“每个键的额外32字节↔值条目HashMap的开销是
因此: – 48个字节,每个条目加36个字节“ ???

我无法理解这些结论是如何产生的,即我们如何遇到关于哈希映射的最终内存细节。

您可能想要阅读此SO问题。 对象开销将在不同的CPU架构,VM实现之间以及不同的Java版本之间变化(例如,OOPS,还有fixnums等的建议)。

但让 我们自己看看 OpenJDK 7, HashMap类:


HashMap开销是48个字节

家政信息。 大概是8个字节。

实现中有三个字段,用于保存由keySet()values()entrySet()方法创建的视图。 三个指针,即32位机器上的12个字节

 // from AbstractMap transient volatile Set keySet = null; transient volatile Collection values = null; // from HashMap private transient Set> entrySet = null 

有三个int字段: sizethresholdmodCount12个字节。

有一个float字段: loadFactor4字节。

表指针本身( Entry[] table )。 4字节。

static final字段不计算,它们是编译时常量)

所有这些都为我们提供了一个HashMap实例的40字节成本。 它不是48字节,我不知道为什么。 也许我错过了什么,也许你的文字提到了其他版本。 这些事情有时会有所改变。 过去可能有一个额外的领域。 也许它填充了40到48个字节(但它不应该)。


数组的16 +(条目* 4个字节)

在构造HashMap时实例化Entry[] table ,我们也需要对它进行计数。

实例化的数组需要8个字节的内务处理数据, 4 bytes用于length属性。 这是12个字节 ,而不是16 。再次,不知道它来自哪里。

每个条目都是一个指向Entry对象的指针,因此每个条目有4个字节 。 那很简单。


每个键Additional值输入附加32个字节

再次, 8字节的家务。

现在,领域:

 final K key; // a reference, 4 bytes V value; // a reference, 4 bytes Entry next; // a reference, 4 bytes final int hash; // an integer primitive, 4 bytes 

16个字节。

这是每个条目的最终计数为24个字节 。 再说一遍,那不是36。


我不知道你在那里得到的数字来自哪里。 那可能是IBM的虚拟机吗? 这可能是64位操作系统吗? 也许家政信息现在是16字节(Java 8会改变什么吗?)。

无论如何,我试图根据我的最佳知识计算内存消耗。