1. 程式人生 > >JDK源碼學習筆記——Object

JDK源碼學習筆記——Object

源碼解析 同步方法 time_wait 基礎 value 篩選 17. vat pro

一、源碼解析

public class Object {

    /**
     * 一個本地方法,具體是用C(C++)在DLL中實現的,然後通過JNI調用
     */
    private static native void registerNatives();

    /**
     * 對象初始化時自動調用此方法
     */
    static {
        registerNatives();
    }

    /**
     * 返回此Object的運行時類
     */
    public final native Class<?> getClass();

    
/** * hashCode的常規協定是: * 1.在java應用程序執行期間,在對同一對象多次調用hashCode()方法時,必須一致地返回相同的整數,前提是將對象進行equals比較時所用的信息沒有被修改。 * 從某一應用程序的一次執行到同一應用程序的另一次執行,該整數無需保持一致。 * 2.如果根據equals(object)方法,兩個對象是相等的,那麽對這兩個對象中的每個對象調用hashCode方法都必須生成相同的整數結果。 * 3.如果根據equals(java.lang.Object)方法,兩個對象不相等,那麽對這兩個對象中的任一對象上調用hashCode()方法不要求一定生成不同的整數結果。 * 但是,程序員應該意識到,為不相等的對象生成不同整數結果可以提高哈希表的性能。
*/ public native int hashCode(); /** * 這裏比較的是對象的內存地址 */ public boolean equals(Object obj) { return (this == obj); } /** * 本地clone方法,用於對象的復制 */ protected native Object clone() throws CloneNotSupportedException; /** * 返回該對象的字符串表示,非常重要的方法 * getClass().getName();獲取字節碼文件的對應全路徑名例如java.lang.Object * Integer.toHexString(hashCode());將哈希值轉成16進制數格式的字符串。
*/ public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } /** * 不能被重寫,用於喚醒一個在因等待該對象(調用了wait方法)被處於等待狀態(waiting 或 time_wait)的線程,該方法只能同步方法或同步塊中調用 */ public final native void notify(); /** * 不能被重寫,用於喚醒所有在因等待該對象(調用wait方法)被處於等待狀態(waiting或time_waiting)的線程,該方法只能同步方法或同步塊中調用 */ public final native void notifyAll(); /** * 不能被重寫,用於在線程調用中,導致當前線程進入等待狀態(time_waiting),timeout單位為毫秒,該方法只能同步方法或同步塊中調用,超過設置時間後線程重新進入可運行狀態 */ public final native void wait(long timeout) throws InterruptedException; public final void wait(long timeout, int nanos) throws InterruptedException { if (timeout < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos > 0) { timeout++; } wait(timeout); } /** * 在其他線程調用此對象的notify()方法或notifyAll()方法前,導致當前線程等待。換句話說,此方法的行為就好像它僅執行wait(0)調用一樣。 * 當前線程必須擁有此對象監視器。 * 該線程發布對此監視器的所有權並等待,直到其他線程通過調用notify方法或notifyAll方法通知在此對象的監視器上等待的線程醒來, * 然後該線程將等到重新獲得對監視器的所有權後才能繼續執行。 */ public final void wait() throws InterruptedException { wait(0); } /** * 這個方法用於當對象被回收時調用,這個由JVM支持,Object的finalize方法默認是什麽都沒有做,如果子類需要在對象被回收時執行一些邏輯處理,則可以重寫finalize方法。 */ protected void finalize() throws Throwable { } }

二、clone()

  淺拷貝

  數組類型默認可以直接克隆,而其他對象實現clone需要先實現Cloneable接口,否則拋出CloneNotSupportedException異常

  參考 【java基礎之jdk源碼】Object

三、equals() 和 hashCode()

  1、兩個obj,如果equals()相等,hashCode()一定相等。
   兩個obj,如果hashCode()相等,equals()不一定相等(Hash散列值有沖突的情況,雖然概率很低)。

  2、重寫equals時要重寫hashcode

參考:Java中的equals()和hashcode()之間關系

   equals()和hashCode()區別?

   詳解 equals() 方法和 hashCode() 方法

四、finalize()

JVM垃圾回收機制中做了詳細介紹:

對於可達性分析算法而言,若要判斷一個對象死亡,需要經歷兩次標記階段。

第一次標記:對象在進行可達性分析後發現沒有與GCRoots相連的引用鏈,則該對象被第一次標記並進行一次篩選,篩選條件為是否有必要執行該對象的finalize方法

  若對象沒有覆蓋finalize方法或者該finalize方法是否已經被虛擬機執行過了,則均視作不必要執行該對象的finalize方法,即該對象將會被回收。

  若對象覆蓋了finalize方法並且該finalize方法並沒有被執行過,這個對象會被放置在一個叫F-Queue的隊列中,之後會由虛擬機自動建立的、優先級低的Finalizer線程去執行

第二次標記:對F-Queue中對象進行第二次標記

  如果對象在finalize方法中拯救了自己,即關聯上了GCRoots引用鏈,那麽在第二次標記的時候該對象將從“即將回收”的集合中移除

  如果對象還是沒有拯救自己,那就會被回收

參考:關於finalize()   finalize()方法

參考資料:

1、【java基礎之jdk源碼】Object

2、Object源碼解析(JDK1.8)

3、java源碼閱讀Object

4、JVM垃圾回收機制

JDK源碼學習筆記——Object