1. 程式人生 > >Java中Object類hashCode的底層實現

Java中Object類hashCode的底層實現

synchronizer.cpp
471
static markOop ReadStableMark (oop obj) {
  markOop mark = obj->mark() ;
  if (!mark->is_being_inflated()) {
    return mark ;       // normal fast-path return
  }

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


603
intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
  if (UseBiasedLocking) {
    // NOTE: many places throughout the JVM do not expect a safepoint
    // to be taken here, in particular most operations on perm gen
    // objects. However, we only ever bias Java instances and all of
    // the call sites of identity_hash that might revoke biases have
    // been checked to make sure they can handle a safepoint. The
    // added check of the bias pattern is to avoid useless calls to
    // thread-local storage.
    if (obj->mark()->has_bias_pattern()) {
      // Box and unbox the raw reference just in case we cause a STW safepoint.
      Handle hobj (Self, obj) ;
      // Relaxing assertion for bug 6320749.
      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");
    }
  }

  // hashCode() is a heap mutator ...
  // Relaxing assertion for bug 6320749.
  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);

  // object should remain ineligible for biased locking
  assert (!mark->has_bias_pattern(), "invariant") ;

  if (mark->is_neutral()) {
    hash = mark->hash();              // this is a normal header
    if (hash) {                       // if it has hash, just return it
      return hash;
    }
    hash = get_next_hash(Self, obj);  // allocate a new hash code
    temp = mark->copy_set_hash(hash); // merge the hash code into header
    // use (machine word version) atomic operation to install the hash
    test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
    if (test == mark) {
      return hash;
    }
    // If atomic operation failed, we must inflate the header
    // into heavy weight monitor. We could add more code here
    // for fast path, but it does not worth the complexity.
  } else if (mark->has_monitor()) {
    monitor = mark->monitor();
    temp = monitor->header();
    assert (temp->is_neutral(), "invariant") ;
    hash = temp->hash();
    if (hash) {
      return hash;
    }
    // Skip to the following code to reduce code size
  } else if (Self->is_lock_owned((address)mark->locker())) {
    temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
    assert (temp->is_neutral(), "invariant") ;
    hash = temp->hash();              // by current thread, check if the displaced
    if (hash) {                       // header contains hash code
      return hash;
    }
    // WARNING:
    //   The displaced header is strictly immutable.
    // It can NOT be changed in ANY cases. So we have
    // to inflate the header into heavyweight monitor
    // even the current thread owns the lock. The reason
    // is the BasicLock (stack slot) will be asynchronously
    // read by other threads during the inflate() function.
    // Any change to stack may not propagate to other threads
    // correctly.
  }

  // Inflate the monitor to set hash code
  monitor = ObjectSynchronizer::inflate(Self, obj);
  // Load displaced header and check it has hash code
  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); // merge hash code into header
    assert (temp->is_neutral(), "invariant") ;
    test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);
    if (test != mark) {
      // The only update to the header in the monitor (outside GC)
      // is install the hash code. If someone add new usage of
      // displaced header, please update this code
      hash = test->hash();
      assert (test->is_neutral(), "invariant") ;
      assert (hash != 0, "Trivial unexpected object/monitor header usage.");
    }
  }
  // We finally get the hash
  return hash;
}

我們看到最終還是 嘗試用 mark->hash()獲取hash的

相關推薦

JavaObjecthashCode底層實現

synchronizer.cpp 471 static markOop ReadStableMark (oop obj) { markOop mark = obj->mark() ; if (!mark->is_being_inflated()) { return mark ;

javaObject是怎麽回事,幹嘛使的?舉例說明!

urn 。。 als tex index all inner ret load 1.Object Class Object類的作用:m a r k - t o- w i n:(視頻下載) (全部書籍) 在java中,因為所有的類都有共性,所以java的締造者們

javaObject的getClass方法有什麽用以及怎麽使用?

全部 pan spa 下載 index person finalize Beginner ret Object類的getClass的用法: (視頻下載) (全部書籍) Object類中有一個getClass方法,m a r k- t o- w i n:它會返回一個你

JAVAObject的equals()方法的使用

先來看一下官方API中對Object類的equals()方法的介紹: equals public boolean equals(Object obj) 指示其他某個物件是否與此物件“相等”。 引數: obj - 要與之比較的引用物件。 返回: 如果

JAVAObject的toString()方法

toString public String toString() 返回該物件的字串表示。通常,toString 方法會返回一個“以文字方式表示”此物件的字串。結果應是一個簡明但易於讀懂的資訊表示式。建議所有子類都重寫此方法。 Object 類的 toS

javaPOJO為什麼要實現序列化

序列化就是一種用來處理物件流的機制,所謂物件流也就是將物件的內容進行流化。可以對流化後的物件進行讀寫操作,也可將流化後的物件傳輸於網路之間。序列化是為了解決在對物件流進行讀寫操作時所引發的問題。序列化的實現:將需要被序列化的類實現Serializable介面,該介面沒有需要實現的方法,impleme

javaObject

1.什麼是Object類?有哪些常用方法?   答:1).Object類是所有類的父類,位於java.lang包中。    2).陣列也是Object類的子類。    3).Object類的常用方法有:

Java Object的方法

Java是單根繼承結構語言,也就是說,Java中所有的類都有一個共同的祖先,這個祖先就是Object類。 如圖所示:Object類中的方法 說明:  1、hashCode和equals函式用來判斷物件是否相同,   ​ equals()用於確認

javaObject的使用理解

Object類的概述 A:Object類概述 類層次結構的根類 所有類都直接或者間接的繼承自該類 B:構造方法 public Object() 回想面向物件中為什麼說: 子類的構造方法預設訪

javaObject、包裝詳解

Object類 Object是java中的基類,所有的類預設都會繼承Object類,所以所有的類都可以通過Object類接收,完成向上轉型,實現引數統一化。 String覆寫的兩個重要的Object方法

JAVAObject的方法以及finalize函式作用

Object是所有類的父類,任何類都預設繼承Object。 一、Object類中的方法 1.clone方法 保護方法,實現物件的淺複製,只有實現了Cloneable接口才可以呼叫該方法,否則丟擲CloneNotSupportedException異常。 主要是JA

javaobject原始碼

package java.lang; public class Object { /* 一個本地方法,具體是用C(C++)在DLL中實現的,然後通過JNI呼叫。*/ private static native void registerNa

javaObject的函式詳解

1.clone方法(淺拷貝) 保護方法,實現物件的淺複製,只有實現了Cloneable接口才可以呼叫該方法,否則丟擲CloneNotSupportedException異常。 主要是JAVA裡除了8種基本型別傳引數是值傳遞,其他的類物件傳引數都是引用傳遞,我們有時候不希望在方法裡講引數改變,

JavaObject的方法(toString方法和equals方法)

Object是所有類的父類(國外成為超類superclass),Object類的方法是相當少的(理解為教室人越多,他們的共同點越少)。 一:toString方法 Object的toString()方法幫助我們返回一個字串,這個字串的格式是固定的:類名@hashcode。

Java 為什麼要實現序列化呢 / JAVA序列化和反序列化的靜態成員問題

很多人覺得自己寫得 Java 程式碼中,新建的 pojo 物件要實現序列化是為了要儲存到硬碟上,其實呢,實現序列化和儲存到硬碟上沒有必然的關係。 以下圖舉例: 假設左邊的是你的電腦,也就是客戶端,右邊的是伺服器。之前你的客戶端和伺服器可能都在同一個電腦上,都是 Windows 下,那麼右邊的伺服器也可以放

javaObject的finalize()方法的理解

看java api文件的過程中,有時候會發現並非想象中的那麼的通熟易懂,這個時候需要耐心、仔細的看,再加上一定的知識儲備,就更容易看懂了。除此之外,從文件中提煉有用資訊的能力也很重要! 看到finalize()方法的時候覺得很陌生,因為幾乎從沒用過。今天開啟a

JavaObject的方法

Object類是所有類的父類,位於java.lang包中,陣列也是Object類的子類 方法有:equals、toString、

javaStringhashCode方法實現

public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value;

JAVA返回型使用泛型T和Object有什麽區別?

some http cast one gpo aud pre 使用 安全 最近在讀jackson源碼的時候發現有段代碼返回類型寫的是<T> T,而我自己一般寫的是Object。上網搜了下這個語法糖,在stackoverflow上找到一個比較簡單易懂的解釋,搬運過

Object,scanner,String,StringBuffer,Java基本型的包裝型等

Object類scanner Scanner類 String和StringBuffer java中基本類型的包裝類型 math類的幾個常用方法 一、Scanner類 Scanner類:簡單文本掃描器1、鍵盤錄入步驟:(1)需要創建鍵盤錄入對象:Scanner 鍵盤錄入對象=new Scan