我正在研究Hash Map的内部结构,其中我遇到了以下细节:
实现是一个HashMap $ Entry对象数组:
每个HashMap $ Entry包含: - int KeyHash - 下一个对象 - 对象键 - 对象值
默认容量为16个条目
空大小为128字节
HashMap的开销是48字节,加上(16 +(条目* 4字节)) array - 加上HashMap $ Entry对象的开销
每个键附加32字节↔值条目HashMap的开销为
因此: - 48个字节,每个条目加36个字节
任何人都可以解释我“HashMap的开销为48字节,加上(16 +(条目* 4字节))
数组“和”每个键附加32字节↔值条目HashMap的开头是
因此: - 48个字节,每个条目加36个字节“ ???
我无法理解这些结论是如何产生的,即我们如何看到关于哈希映射的最终内存细节。
答案 0 :(得分:2)
You might want to read this SO question.对象开销在不同的CPU架构,VM实现之间以及不同的Java版本之间会有所不同(例如OOPS,还有fixnums的建议等。)
对于OpenJDK 7,HashMap
类
的开销为48字节
HashMap
家政信息。 大概是8个字节。
实施中有三个字段用于保存keySet()
,values()
和entrySet()
方法所做的视图。三个指针,即32位机器上的 12个字节。
// from AbstractMap
transient volatile Set<K> keySet = null;
transient volatile Collection<V> values = null;
// from HashMap
private transient Set<Map.Entry<K,V>> entrySet = null
有三个int
字段:size
,threshold
和modCount
。 12个字节。
有一个float
字段:loadFactor
。 4个字节。
表指针本身(Entry[] table
)。 4个字节。
(static final
字段不计算,它们是编译时常量)
所有这些都为我们提供了 40字节 HashMap
实例的固定成本。它不是48字节,我不知道为什么。也许我错过了一些东西,也许你的文字提到了其他版本。这些事情有时会有所改变。过去可能有一个额外的领域。也许它填充了40到48个字节(但它不应该)。
16 +(条目* 4字节)数组
构造Entry[] table
时HashMap
表被实例化,我们也需要计算它。
实例化数组需要 8个字节的内务数据,4 bytes
属性length
。那是 12个字节,而不是16.再次,不知道它来自哪里。
每个条目都是指向Entry
对象的指针,因此每个条目的 4个字节。这很容易。
每个键增加32个字节↔值条目
再次, 8字节的管家。
现在,字段:
final K key; // a reference, 4 bytes
V value; // a reference, 4 bytes
Entry<K,V> next; // a reference, 4 bytes
final int hash; // an integer primitive, 4 bytes
16个字节。
每个条目的最终计数 24个字节。再说一遍,那不是36。
我不知道你在那里得到的数字来自哪里。那可能是IBM虚拟机吗?这可能是64位操作系统吗?也许家政信息现在是16字节(Java 8会改变什么吗?)。
无论如何,我试着根据我的最佳知识来计算内存消耗。