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