JVM如何确保System.identityHashCode()永远不会改变?

时间:2009-06-30 10:57:42

标签: java jvm hashcode heap-memory

通常, Object.hashCode() 的默认实现是内存中对象的已分配地址的某些功能(尽管 JLS 并未强制执行此操作)。鉴于VM在内存中分流对象,为什么 System.identityHashCode() 返回的值在对象的生命周期内永远不会改变?

如果是“一次性”计算(对象的hashCode计算一次并藏在对象标题或其他内容中),那么这是否意味着两个对象可能具有相同的{{ 1}}(如果它们碰巧首先在内存中的同一地址分配)?

5 个答案:

答案 0 :(得分:38)

现代JVM将值保存在对象标头中。我认为该值通常仅在首次使用时计算,以便将在对象分配中花费的时间保持在最小值(有时低至十几个周期)。可以编译公共Sun JVM,以便所有对象的标识哈希码始终为1。

多个对象可以具有相同的标识哈希码。这就是哈希码的本质。

答案 1 :(得分:16)

在回答第二个问题时,无论实现如何,多个对象都可以具有相同的identityHashCode。

请参阅bug 6321873,了解javadoc中措词的简要讨论,以及展示非唯一性的程序。

答案 2 :(得分:2)

HotSpot中对象的标题由类指针和“标记”字组成。

标记字的数据结构的源代码可以在markOop.hpp文件中找到。在此文件中有一条描述标记字的内存布局的注释:

  

hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)

在这里我们可以看到32位系统上普通Java对象的标识哈希码保存在标记字中,长度为25位。

答案 3 :(得分:0)

实现散列函数的一般准则是:

  • 同一个对象应返回一致的hashCode ,它不应随时间变化或依赖于任何变量信息(例如,由随机数或可变成员字段值播种的算法
  • 哈希函数应具有良好的随机分布,并且我的意思是,如果您将哈希码视为存储桶,则2个对象应尽可能映射到不同的存储区(哈希码)。 2个对象具有相同哈希码的可能性应该很少 - 尽管可以发生。

答案 4 :(得分:-3)

据我所知,这是为了返回引用而实现的,该引用在对象生存期内永远不会改变。