美團(tuán)面試題:hashCode 和對(duì)象的內(nèi)存地址有什么關(guān)系?
閱讀本文大概需要 4 分鐘。
來(lái)自: juejin.cn/post/6971946031764209678
System.out.println(new Object());
java.lang.Object@6659c656
@符號(hào)后面的是什么?是 hashcode 還是對(duì)象的內(nèi)存地址?還是其他的什么值?@后面的只是對(duì)象的 hashcode 值,16進(jìn)制展示的 hashcode 而已,來(lái)驗(yàn)證一下:Object o = new Object();
int hashcode = o.hashCode();
// toString
System.out.println(o);
// hashcode 十六進(jìn)制
System.out.println(Integer.toHexString(hashcode));
// hashcode
System.out.println(hashcode);
// 這個(gè)方法,也是獲取對(duì)象的 hashcode;不過(guò)和 Object.hashcode 不同的是,該方法會(huì)無(wú)視重寫的hashcode
System.out.println(System.identityHashCode(o));
java.lang.Object@6659c656
6659c656
1717159510
1717159510
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 = 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 = 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 ;
}
value &= markOopDesc::hash_mask;
if (value == 0) value = 0xBAD ;
assert (value != markOopDesc::no_hash, "invariant") ;
TEVENT (hashCode: GENERATE) ;
return value;
}
hashCode 的全局變量控制的,默認(rèn)為5;而這個(gè)變量的定義在另一個(gè)頭文件里:product(intx, hashCode, 5,
"(Unstable) select hashCode generation algorithm" )
java -XX:+PrintFlagsFinal -version | grep hashCode
intx hashCode = 5 {product}
openjdk version "1.8.0_282"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_282-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.282-b08, mixed mode)
-XX:hashCode=N
第 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();
}
第 1 種算法
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 = intptr_t(obj) >> 3 ;
value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
}
intptr_t 類型指針第 2 種算法
if (hashCode == 2) {
value = 1 ; // for sensitivity testing
}
-XX:hashCode=2來(lái)開(kāi)啟這個(gè)算法,看看 hashCode 結(jié)果是不是都變成 1 了。第 3 種算法
if (hashCode == 3) {
value = ++GVars.hcSequence ;
}
System.out.println(new Object());
System.out.println(new Object());
System.out.println(new Object());
System.out.println(new Object());
System.out.println(new Object());
System.out.println(new Object());
//output
java.lang.Object@144
java.lang.Object@145
java.lang.Object@146
java.lang.Object@147
java.lang.Object@148
java.lang.Object@149
第 4 種算法
if (hashCode == 4) {
value = intptr_t(obj) ;
}
第 5 種算法
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 ;
}
推薦閱讀:
B 站焊武帝爆火出圈:純手工拼晶體管自制 CPU,耗時(shí)半年,可跑程序
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。
朕已閱 

