HashCode

2018-03-26  本文已影响0人  CelloRen

hashCode在Object类中实现,在此先不做引申,仅介绍一个对象的hashCode是怎么产生的:
首先查看Java.lang.Object:

// Object is the root of the class hierarchy.
// All objects, including arrays, implement the methods of this class.
public class Object {
     // Returns a hash code value for the object. This method is
     // supported for the benefit of hash tables such as those provided by
     // HashMap
      public native int hashCode();
}

在Object类里是没有直接实现hashCode()方法的,我们只知道这是一个native方法,即非java实现的。
它的实现可以在OpenJDK里找到(openjdk/jdk/src/share/native/java/lang/Object.c):

static JNINativeMethod methods[] = {
    {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
    {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
    {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
    {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};

可以知道又和JVM_IHashCode有关;
再找到JVM_IHashCode的定义(openjdk\hotspot\src\share\vm\prims\jvm.cpp):

// java.lang.Object ///////////////////////////////////////////////
JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
  JVMWrapper("JVM_IHashCode");
  // as implemented in the classic virtual machine; return 0 if object is NULL
  return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
JVM_END

可以知道又和FastHashCode方法有关(openjdk\hotspot\src\share\vm\runtime\synchronizer.cpp);


如图所示

其中,FastHashCode中又有:

  hash = get_next_hash(Self, obj);  // allocate a new hash code

可知实现在get_next_hash()方法中,其核心的代码是:

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 ;
  }

其中在thread.cpp中有定义:

// thread-specific hashCode stream generator state - Marsaglia shift-xor form
  _hashStateX = os::random() ;
  _hashStateY = 842502087 ;
  _hashStateZ = 0x8767 ;    // (int)(3579807591LL & 0xffff) ;
  _hashStateW = 273326509 ;

于是我们可以知道JDK8的hashCode()的产生是基于一个随机数和三个确定数的,至于为什么get_next_hash()方法中的核心代码是这样,这要援引一篇论文:
Xorshift RNGs


部分截图

再深入就要涉及数学的推导和矩阵的运算了,我也没有完全吃透,有兴趣的可以看看这篇论文。
思考:
1.为什么JDK8的hashCode不引入对象的地址参与运算呢?
2.既然是基于hash,那么必然有几率产生碰撞,碰撞产生时如何处理?
3.hashCode和equal方法的联系
4.hashCode和hashMap的联系

上一篇下一篇

猜你喜欢

热点阅读