Java语言中,Object对象有个特殊的方法:hashcode(), hashcode()表示的是JVM虚拟机为这个Object对象分配的一个int类型的数值,JVM会使用对象的hashcode值来提高对HashMap、Hashtable哈希表存取对象的使用效率。
关于Object对象的hashCode()返回值,网上对它就是一个简单的描述:“JVM根据某种策略生成的”,那么这种策略到底是什么呢?我有一个毛病,遇到这种含糊其辞的东西,就想探个究竟,所以,本文就将hashCode()本地方法的实现给扒出来,也给大家在了解hashCode()的过程中提供一点点帮助吧。
本文将根据openJDK 7源码,向展示Java语言中的Object对象的hashCode() 生成的神秘面纱,我将一步一步地向读者介绍Java Object 的hashcode()方法到底底层调用了什么函数。为了更好地了解这个过程,你可以自己下载openJDK 7 源码,亲自查看和跟踪源码,了解hashCode()的生成过程:
openJDK 7 下载地址1:http://download.java.net/openjdk/jdk7 (官网,下载速度较慢)
openJDK 7 下载地址2 :openjdk-7-fcs-src-b147-27_jun_2011.zip (csdn 网友提供的资源,很不错)
1.查看openJDK 关于 java.lang.Object类及其hashcode()方法的定义:
进入openjdk\jdk\src\share\classes\java\lang目录下,可以看到 Object.java源码,打开,查看hashCode()的定义如下所示:
- public native int hashCode();
即该方法是一个本地方法,Java将调用本地方法库对此方法的实现。由于Object类中有JNI方法调用,按照JNI的规则,应当生成JNI 的头文件,在此目录下执行
javah -jni java.lang.Object
指令,将生成一个
java_lang_Object.h
头文件,该头文件将在后面用到它
java_lang_Object.h头文件关于hashcode方法的信息如下所示:
-
-
-
-
-
- JNIEXPORT jint JNICALL Java_java_lang_Object_hashCode
- (JNIEnv *, jobject);
2. Object对象的hashCode()方法在C语言文件Object.c中实现
打开openjdk\jdk\src\share\native\java\lang\目录,查看Object.c文件,可以看到hashCode()的方法被注册成有JVM_IHashCode方法指针来处理:
- #include <stdio.h>
- #include <signal.h>
- #include <limits.h>
-
- #include "jni.h"
- #include "jni_util.h"
- #include "jvm.h"
-
- #include "java_lang_Object.h"
-
- 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},
- };
-
- JNIEXPORT void JNICALL
- Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
- {
- (*env)->RegisterNatives(env, cls,
- methods, sizeof(methods)/sizeof(methods[0]));
- }
-
- JNIEXPORT jclass JNICALL
- Java_java_lang_Object_getClass(JNIEnv *env, jobject this)
- {
- if (this == NULL) {
- JNU_ThrowNullPointerException(env, NULL);
- return 0;
- } else {
- return (*env)->GetObjectClass(env, this);
- }
- }
3.JVM_IHashCode方法指针在 openjdk\hotspot\src\share\vm\prims\jvm.cpp中定义,如下:
- JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
- JVMWrapper("JVM_IHashCode");
-
- return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
- JVM_END
如上可以看出,JVM_IHashCode方法中调用了ObjectSynchronizer::FastHashCode方法
4. ObjectSynchronizer::fashHashCode方法的实现:
ObjectSynchronizer::fashHashCode()方法在 openjdk\hotspot\src\share\vm\runtime\synchronizer.cpp 文件中实现,其核心代码实现如下所示:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- static inline intptr_t get_next_hash(Thread * Self, oop obj) {
- intptr_t value = 0 ;
- if (hashCode == 0) {
-
-
-
-
- value = os::random() ;
- } else
- if (hashCode == 1) {
-
-
-
- intptr_t addrBits = intptr_t(obj) >> 3 ;
- value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
- } else
- if (hashCode == 2) {
- value = 1 ;
- } else
- if (hashCode == 3) {
- value = ++GVars.hcSequence ;
- } else
- if (hashCode == 4) {
- value = intptr_t(obj) ;
- } else {
-
-
-
- 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 ;
- }
-
- value &= markOopDesc::hash_mask;
- if (value == 0) value = 0xBAD ;
- assert (value != markOopDesc::no_hash, "invariant") ;
- TEVENT (hashCode: GENERATE) ;
- return value;
- }
-
- intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
- if (UseBiasedLocking) {
-
-
-
-
-
-
-
- if (obj->mark()->has_bias_pattern()) {
-
- Handle hobj (Self, obj) ;
-
- assert (Universe::verify_in_progress() ||
- !SafepointSynchronize::is_at_safepoint(),
- "biases should not be seen by VM thread here");
- BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
- obj = hobj() ;
- assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
- }
- }
-
-
-
- assert (Universe::verify_in_progress() ||
- !SafepointSynchronize::is_at_safepoint(), "invariant") ;
- assert (Universe::verify_in_progress() ||
- Self->is_Java_thread() , "invariant") ;
- assert (Universe::verify_in_progress() ||
- ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
-
- ObjectMonitor* monitor = NULL;
- markOop temp, test;
- intptr_t hash;
- markOop mark = ReadStableMark (obj);
-
-
- assert (!mark->has_bias_pattern(), "invariant") ;
-
- if (mark->is_neutral()) {
- hash = mark->hash();
- if (hash) {
- return hash;
- }
- hash = get_next_hash(Self, obj);
- temp = mark->copy_set_hash(hash);
-
- test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
- if (test == mark) {
- return hash;
- }
-
-
-
- } else if (mark->has_monitor()) {
- monitor = mark->monitor();
- temp = monitor->header();
- assert (temp->is_neutral(), "invariant") ;
- hash = temp->hash();
- if (hash) {
- return hash;
- }
-
- } else if (Self->is_lock_owned((address)mark->locker())) {
- temp = mark->displaced_mark_helper();
- assert (temp->is_neutral(), "invariant") ;
- hash = temp->hash();
- if (hash) {
- return hash;
- }
-
-
-
-
-
-
-
-
-
- }
-
-
- monitor = ObjectSynchronizer::inflate(Self, obj);
-
- mark = monitor->header();
- assert (mark->is_neutral(), "invariant") ;
- hash = mark->hash();
- if (hash == 0) {
- hash = get_next_hash(Self, obj);
- temp = mark->copy_set_hash(hash);
- assert (temp->is_neutral(), "invariant") ;
- test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);
- if (test != mark) {
-
-
-
- hash = test->hash();
- assert (test->is_neutral(), "invariant") ;
- assert (hash != 0, "Trivial unexpected object/monitor header usage.");
- }
- }
-
- return hash;
- }
源码来源: minglisoft.cn/technology