通常,
Object.hashCode()
的默认实现是内存中对象分配地址的某个函数(尽管Java语言规范没有强制要求)。鉴于虚拟机在内存中分流对象,为什么 System.identityHashCode()
返回的值在对象的生命周期内永远不会改变?
如果是“一次性”计算(对象的
hashCode
计算一次并隐藏在对象头或其他内容中),那么这是否意味着两个对象可能具有相同的 identityHashCode
(如果它们碰巧首先分配在内存中的同一地址)?
现代 JVM 将值保存在对象头中。我相信该值通常仅在第一次使用时计算,以便将对象分配所花费的时间保持在最低限度(有时低至十几个周期)。常见的 Sun JVM 可以编译为所有对象的身份哈希码始终为 1。
多个对象可以具有相同的身份哈希码。这就是哈希码的本质。
回答第二个问题,无论实现如何,多个对象都可能具有相同的identityHashCode。
请参阅 bug 6321873,了解有关 javadoc 中措辞的简短讨论以及演示非唯一性的程序。
HotSpot 中对象的标头由类指针和“标记”字组成。
markOop.hpp
文件中找到。在这个文件中有一条注释描述了标记字的内存布局:
hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
在这里我们可以看到,32位系统上普通Java对象的身份哈希码保存在标记字中,长度为25位。
实现哈希函数的一般准则是: