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位。

据我所知,这是实现返回引用,永远不会改变对象的生命周期。