Object的hashCode返回值会重复吗

  • Post author:
  • Post category:其他


首先,看看Object的hashCode注释吧。

在这里插入图片描述

根据上图注释来解释,红框内容说明hashCode返回值与对象内存地址有一定关系。但是看看open-jdk源码就会发现,hashCode可不这么简单。

static inline intptr_t get_next_hash(Thread * Self, oop obj) {
  intptr_t value = 0 ;
  if (hashCode == 0) {
     // This form uses an unguarded global Park-Miller RNG,
     // so it's possible for two threads to race and generate the same RNG.
     // On MP system we'll have lots of RW access to a global, so the
     // mechanism induces lots of coherency traffic.
     value = os::random() ;
  } else
  if (hashCode == 1) {
     // This variation has the property of being stable (idempotent)
     // between STW operations.  This can be useful in some of the 1-0
     // synchronization schemes.
     intptr_t addrBits = cast_from_oop<intptr_t>(obj) >> 3 ;
     value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
  } else
  if (hashCode == 2) {
     value = 1 ;            // for sensitivity testing
  } else
  if (hashCode == 3) {
     value = ++GVars.hcSequence ;
  } else
  if (hashCode == 4) {
     value = cast_from_oop<intptr_t>(obj) ;
  } else {
     // Marsaglia's xor-shift scheme with thread-specific state
     // This is probably the best overall implementation -- we'll
     // likely make this the default in future releases.
     unsigned t = Self->_hashStateX ;
     t ^= (t << 11) ;
     Self->_hashStateX = Self->_hashStateY ;
     Self->_hashStateY = Self->_hashStateZ ;
     Self->_hashStateZ = Self->_hashStateW ;
     unsigned v = Self->_hashStateW ;
     v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
     Self->_hashStateW = v ;
     value = v ;
  }

根据上面代码可以总结出6种计算hashCode的方式:

  • 策略为0:返回随机数
  • 策略为1:返回 根据对象的内存地址进行计算的结果
  • 策略为2:返回1
  • 策略为3:返回一个序列
  • 策略为4:返回 根据对象的内存地址转换成的int值
  • 其他: 返回 根据线程状态和三个定值进行计算的结果

    所以,只有使用了策略1和4,hashCode返回值才可能与内存地址有关系。

那jdk8到底使用的什么计算方式呢?

我们可以通过添加 -XX:+PrintFlagsFinal 发现, jdk8的hashCode设置为5,也就是使用其他实现。

在这里插入图片描述

而且,我们可以通过 -XX:hashCode 来修改策略,如下,我将策略改成2(-XX:hashCode=2),发现返回值真的是1。

在这里插入图片描述


综上所述,Object hashCode方法的返回值不一定和对象内存有关,我们可以通过 -XX:hashCode 来修改策略,调整hashCode计算方式。


那我们回到标题,hashCode会不会重复呢?

1.因为hashCode只是计算一次,保存在对象头中,就算用内存地址相关策略,也会因为垃圾回收等导致不同对象的内存地址一样,从而hashCode冲突。

2.使用其他策略,随机数等也是无法保障唯一性的。


可见,hashCode的计算方式是无法保证唯一性的,还是可能会重复的。



版权声明:本文为weixin_42260270原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。