JVM如何确保System.identityHashCode()永远不会改变?
通常, Object.hashCode()
的默认实现是内存中对象的分配地址的一些函数(虽然这不是JLS所要求的)。 鉴于VM分stream内存中的对象,为什么System.identityHashCode()
返回的值永远不会在对象的生命期内更改?
如果是“一次性”计算(对象的hashCode
被计算一次并隐藏在对象头部或某物中),那么这是否意味着两个对象可能具有相同的identityHashCode
(如果它们碰巧是首先分配的在内存中的相同地址)?
现代JVM将对象头中的值保存起来。 我相信这个值通常只是在第一次使用时计算出来,以便将花费在对象分配上的时间降到最低(有时低至十几个周期)。 常见的Sun Java虚拟机可以被编译,以便所有对象的身份哈希码总是1。
多个对象可以具有相同的标识哈希码。 这是哈希码的本质。
在回答第二个问题时,不pipe实现如何,多个对象可能具有相同的identityHashCode。
请参阅错误6321873 ,简要讨论javadoc中的措辞,以及演示非唯一性的程序。
实现散列函数的一般原则是:
- 同一个对象应该返回一个一致的hashCode ,它不应该随着时间而改变或者依赖于任何可变的信息(例如,一个随机数或者可变成员域值
- 哈希函数应该有一个很好的随机分布 ,我的意思是如果你认为哈希码作为桶,2个对象应尽可能映射到不同的桶(哈希码)。 2个对象具有相同的哈希码的可能性应该是罕见的 – 尽pipe可能发生。
HotSpot中对象的标题由类指针和“标记”字组成。
标记字的数据结构的源代码可以在markOop.hpp
文件中find。 在文件中是描述标记字的内存布局的注释:
hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
这里我们可以看到,32位系统上普通Java对象的标识哈希码保存在标记字中,长度为25位。
据我所知,这是实现返回引用,永远不会改变对象的生命周期。