通常,Object.hashCode()的默认实现是内存中对象的已分配地址的某个函数(尽管这不是 JLS强制要求的)。假设 VM 分流了内存中的对象,为什么 System.identityHashCode()返回的值在对象的生命周期内从未改变?
Object.hashCode()
System.identityHashCode()
如果这是一个“一次性”的计算(对象的 hashCode计算一次并隐藏在对象头部或其他地方) ,那么这是否意味着两个对象有可能拥有相同的 identityHashCode(如果它们碰巧首先在内存中的相同地址分配) ?
hashCode
identityHashCode
据我所知,这是为了返回引用而实现的,引用在对象生命周期中永远不会改变。
在回答第二个问题时,不管实现如何,多个对象都可能具有相同的 IdentityHashCode。
有关 javadoc 中的措辞的简要讨论,请参见 窃听器6321873,以及演示非唯一性的程序。
现代 JVM 将值保存在对象头中。我相信这个值通常只在第一次使用时计算,以便将对象分配所花费的时间保持在最低限度(有时甚至低至12个周期)。可以编译公共 Sun JVM,以便所有对象的标识哈希代码始终为1。
多个对象可以有相同的标识哈希代码。这是哈希代码的本质。
实现散列函数的一般准则是:
HotSpot 中对象的头部由一个类指针和一个“标记”字组成。
标记字的数据结构的源代码可以在 markOop.hpp文件中找到。在这个文件中有一个注释描述了标记字的内存布局:
markOop.hpp
hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
在这里,我们可以看到32位系统上普通 Java 对象的标识哈希代码保存在标记字中,它有25位长。