首先,看看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 版权协议,转载请附上原文出处链接和本声明。