国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - Java從JDK源碼角度對Object進行實例分析

Java從JDK源碼角度對Object進行實例分析

2021-03-05 14:25default JAVA教程

這篇文章主要介紹了Java從JDK源碼角度對Object進行實例分析,具有一定借鑒價值,需要的朋友可以參考下。

Object是所有類的父類,也就是說java中所有的類都是直接或者間接繼承自Object類。比如你隨便創建一個classA,雖然沒有明說,但默認是extendsObject的。

后面的三個點"..."表示可以接受若干不確定數量的參數。老的寫法是Objectargs[]這樣,但新版本的java中推薦使用...來表示。例如

publicvoidgetSomething(String...strings)(){}

object是java中所有類的父類,也就是說所有的類,不管是自己創建的類還是系統中的類都繼承自object類,也就是說所有的類在任何場合都可以代替object類,根據里氏替換原則,子類在任何場合都可以代替其父類,而父類卻不一定能代替其子類,java中常說的萬物皆對象說的其實就是這個道理!object類體現了oop思想中的多態,繼承,封裝,抽象四大特性!

object類是所有類的基類,不是數據類型。這個你可以查詢jdk文檔了解,所有類都繼承自Object。

Object...objects這種參數定義是在不確定方法參數的情況下的一種多態表現形式。即這個方法可以傳遞多個參數,這個參數的個數是不確定的。這樣你在方法體中需要相應的做些處理。因為Object是基類,所以使用Object...objects這樣的參數形式,允許一切繼承自Object的對象作為參數。這種方法在實際中應該還是比較少用的。

Object[]obj這樣的形式,就是一個Object數組構成的參數形式。說明這個方法的參數是固定的,是一個Object數組,至于這個數組中存儲的元素,可以是繼承自Object的所有類的對象。

這些基礎東西建議你多看幾遍"Thinkinjava"

Java的Object是所有其他類的父類,從繼承的層次來看它就是最頂層根,所以它也是唯一一個沒有父類的類。它包含了對象常用的一些方法,比如getClass、hashCode、equals、clone、toString、notify、wait等常用方法。所以其他類繼承了Object后就可以不用重復實現這些方法。這些方法大多數是native方法,下面具體分析。

主要的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Object {
    private static native void registerNatives();
    static {
        registerNatives();
    }
    public final native Class<?> getClass();
    public native int hashCode();
    public Boolean equals(Object obj) {
        return (this == obj);
    }
    protected native Object clone() throws CloneNotSupportedException;
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    public final native void notify();
    public final native void notifyAll();
    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);
    }
    public final void wait() throws InterruptedException {
        wait(0);
    }
    protected void finalize() throws Throwable {
    }
}

registerNatives方法

由于registerNatives方法被static塊修飾,所以在加載Object類時就會執行該方法,對應的本地方法為Java_java_lang_Object_registerNatives,如下,

?
1
2
3
4
5
6
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
    methods, sizeof(methods)/sizeof(methods[0]));
}

可以看到它間接調用了JNINativeInterface_結構體的方法,簡單可以看成是這樣:它干的事大概就是將Java層的方法名和本地函數對應起來,方便執行引擎在執行字節碼時根據這些對應關系表來調用C/C++函數,如下面,將這些方法進行注冊,執行引擎執行到hashCode方法時就可以通過關系表來查找到JVM的JVM_IHashCode函數,其中()I還可以得知Java層上的類型應該轉為int類型。這個映射其實就可以看成將字符串映射到函數指針。

?
1
2
3
4
5
6
7
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},
};

getClass方法

getClass方法也是個本地方法,對應的本地方法為Java_java_lang_Object_getClass,如下:

?
1
2
3
4
5
6
7
8
9
10
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);
  }
}

所以這里主要就是看GetObjectClass函數了,Java層的Class在C++層與之對應的則是klassOop,所以關于類的元數據和方法信息可以通過它獲得。

?
1
2
3
4
5
6
7
8
9
JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
 JNIWrapper("GetObjectClass");
 DTRACE_PROBE2(hotspot_jni, GetObjectClass__entry, env, obj);
 klassOop k = JNIHandles::resolve_non_null(obj)->klass();
 jclass ret =
  (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror());
 DTRACE_PROBE1(hotspot_jni, GetObjectClass__return, ret);
 return ret;
JNI_END

hashCode方法

由前面registerNatives方法將幾個本地方法注冊可知,hashCode方法對應的函數為JVM_IHashCode,即

?
1
2
3
4
5
JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
 JVMWrapper("JVM_IHashCode");
 // as implemented in the classic virtual machine; return 0 if object is NULL
 return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
JVM_END

對于hashcode生成的邏輯由synchronizer.cpp的get_next_hash函數決定,實現比較復雜,根據hashcode的不同值有不同的生成策略,最后使用一個hash掩碼處理。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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 ;
        // for sensitivity testing
    } 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;
}

equals方法

這是一個非本地方法,判斷邏輯也十分簡單,直接==比較。

clone方法

由本地方法表知道clone方法對應的本地函數為JVM_Clone,clone方法主要實現對象的克隆功能,根據該對象生成一個相同的新對象(我們常見的類的對象的屬性如果是原始類型則會克隆值,但如果是對象則會克隆對象的地址)。Java的類要實現克隆則需要實現Cloneable接口,if (!klass->is_cloneable())這里會校驗是否有實現該接口。然后判斷是否是數組分兩種情況分配內存空間,新對象為new_obj,接著對new_obj進行copy及C++層數據結構的設置。最后再轉成jobject類型方便轉成Java層的Object類型。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
 JVMWrapper("JVM_Clone");
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
const KlassHandle klass (THREAD, obj->klass());
JvmtiVMObjectAllocEventCollector oam;
if (!klass->is_cloneable()) {
    ResourceMark rm(THREAD);
    THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name());
}
const int size = obj->size();
oop new_obj = NULL;
if (obj->is_javaArray()) {
    const int length = ((arrayOop)obj())->length();
    new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);
} else {
    new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);
}
Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj,
                (size_t)align_object_size(size) / HeapWordsPerlong);
new_obj->init_mark();
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->has_write_region_opt(), "Barrier set does not have write_region");
bs->write_region(MemRegion((HeapWord*)new_obj, size));
if (klass->has_finalizer()) {
    assert(obj->is_instance(), "should be instanceOop");
    new_obj = instanceKlass::register_finalizer(instanceOop(new_obj), CHECK_NULL);
}
return JNIHandles::make_local(env, oop(new_obj));
JVM_END

toString方法

邏輯是獲取class名稱加上@再加上十六進制的hashCode。

notify方法

此方法用來喚醒線程,final修飾說明不可重寫。與之對應的本地方法為JVM_MonitorNotify,ObjectSynchronizer::notify最終會調用ObjectMonitor::notify(TRAPS),這個過程是ObjectSynchronizer會嘗試當前線程獲取freeObjectMonitor對象,不成功則嘗試從全局中獲取。

?
1
2
3
4
5
6
JVM_ENTRY(void, JVM_MonitorNotify(JNIEnv* env, jobject handle))
 JVMWrapper("JVM_MonitorNotify");
 Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
 assert(obj->is_instance() || obj->is_array(), "JVM_MonitorNotify must apply to an object");
 ObjectSynchronizer::notify(obj, CHECK);
JVM_END

ObjectMonitor對象包含一個_WaitSet隊列對象,此對象保存著所有處于wait狀態的線程,用ObjectWaiter對象表示。notify要做的事是先獲取_WaitSet隊列鎖,再取出_WaitSet隊列中第一個ObjectWaiter對象,再根據不同策略處理該對象,比如把它加入到_EntryList隊列中。然后再釋放_WaitSet隊列鎖。它并沒有釋放synchronized對應的鎖,所以鎖只能等到synchronized同步塊結束時才釋放。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
void ObjectMonitor::notify(TRAPS) {
    CHECK_OWNER();
    if (_WaitSet == NULL) {
        TEVENT (Empty-Notify) ;
        return ;
    }
    DTRACE_MONITOR_PROBE(notify, this, object(), THREAD);
    int Policy = Knob_MoveNotifyee ;
    Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notify") ;
    ObjectWaiter * iterator = DequeueWaiter() ;
    if (iterator != NULL) {
        TEVENT (Notify1 - Transfer) ;
        guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
        guarantee (iterator->_notified == 0, "invariant") ;
        if (Policy != 4) {
            iterator->TState = ObjectWaiter::TS_ENTER ;
        }
        iterator->_notified = 1 ;
        ObjectWaiter * List = _EntryList ;
        if (List != NULL) {
            assert (List->_prev == NULL, "invariant") ;
            assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
            assert (List != iterator, "invariant") ;
        }
        if (Policy == 0) {
            // prepend to EntryList
            if (List == NULL) {
                iterator->_next = iterator->_prev = NULL ;
                _EntryList = iterator ;
            } else {
                List->_prev = iterator ;
                iterator->_next = List ;
                iterator->_prev = NULL ;
                _EntryList = iterator ;
            }
        } else
           if (Policy == 1) {
            // append to EntryList
            if (List == NULL) {
                iterator->_next = iterator->_prev = NULL ;
                _EntryList = iterator ;
            } else {
                // CONSIDER: finding the tail currently requires a linear-time walk of
                // the EntryList. We can make tail access constant-time by converting to
                // a CDLL instead of using our current DLL.
                ObjectWaiter * Tail ;
                for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
                assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
                Tail->_next = iterator ;
                iterator->_prev = Tail ;
                iterator->_next = NULL ;
            }
        } else
           if (Policy == 2) {
            // prepend to cxq
            // prepend to cxq
            if (List == NULL) {
                iterator->_next = iterator->_prev = NULL ;
                _EntryList = iterator ;
            } else {
                iterator->TState = ObjectWaiter::TS_CXQ ;
                for (;;) {
                    ObjectWaiter * Front = _cxq ;
                    iterator->_next = Front ;
                    if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
                        break ;
                    }
                }
            }
        } else
           if (Policy == 3) {
            // append to cxq
            iterator->TState = ObjectWaiter::TS_CXQ ;
            for (;;) {
                ObjectWaiter * Tail ;
                Tail = _cxq ;
                if (Tail == NULL) {
                    iterator->_next = NULL ;
                    if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
                        break ;
                    }
                } else {
                    while (Tail->_next != NULL) Tail = Tail->_next ;
                    Tail->_next = iterator ;
                    iterator->_prev = Tail ;
                    iterator->_next = NULL ;
                    break ;
                }
            }
        } else {
            ParkEvent * ev = iterator->_event ;
            iterator->TState = ObjectWaiter::TS_RUN ;
            OrderAccess::fence() ;
            ev->unpark() ;
        }
        if (Policy < 4) {
            iterator->wait_reenter_begin(this);
        }
        // _WaitSetLock protects the wait queue, not the EntryList. We could
        // move the add-to-EntryList operation, above, outside the critical section
        // protected by _WaitSetLock. In practice that's not useful. With the
        // exception of wait() timeouts and interrupts the monitor owner
        // is the only thread that grabs _WaitSetLock. There's almost no contention
        // on _WaitSetLock so it's not profitable to reduce the length of the
        // critical section.
    }
    Thread::SpinRelease (&_WaitSetLock) ;
    if (iterator != NULL && ObjectMonitor::_sync_Notifications != NULL) {
        ObjectMonitor::_sync_Notifications->inc() ;
    }
}

notifyAll方法

與notify方法類似,只是在取_WaitSet隊列時不是取第一個而是取所有。

wait方法

wait方法是讓線程等待,它對應的本地方法是JVM_MonitorWait,間接調用了ObjectSynchronizer::wait,與notify對應,它也是對應調用ObjectMonitor對象的wait方法。該方法較長,這里不貼出來了,大概就是創建一個ObjectWaiter對象,接著獲取_WaitSet隊列鎖將ObjectWaiter對象添加到該隊列中,再釋放隊列鎖。另外,它還會釋放synchronized對應的鎖,所以鎖沒有等到synchronized同步塊結束時才釋放。

?
1
2
3
4
5
6
7
8
9
10
JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
 JVMWrapper("JVM_MonitorWait");
 Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
 assert(obj->is_instance() || obj->is_array(), "JVM_MonitorWait must apply to an object");
 JavaThreadInObjectWaitState jtiows(thread, ms != 0);
 if (JvmtiExport::should_post_monitor_wait()) {
  JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);
 }
 ObjectSynchronizer::wait(obj, ms, CHECK);
JVM_END

finalize方法

這個方法用于當對象被回收時調用,這個由JVM支持,Object的finalize方法默認是什么都沒有做,如果子類需要在對象被回收時執行一些邏輯處理,則可以重寫finalize方法

總結

以上就是本文關于Java從JDK源碼角度對Object進行實例分析的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

原文鏈接:http://www.php.cn/java-article-374699.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 在线播放亚洲 | 免费裸体视频网站 | 国产黄 | 国产成人黄色 | 我要看日本黄色小视频 | 伊人福利视频 | 久久久久久久一区 | 蜜桃视频网站入口 | 久久久久久久成人 | 久久久久无码国产精品一区 | 国产乱叫456 | 日韩成人在线播放 | 91一区二区在线 | 欧洲一级毛片 | 激情视频在线观看 | 国产欧美日韩一区二区三区 | 精品久久久av | 伦一区二区三区中文字幕v亚洲 | 91.成人天堂一区 | 中文字幕一区二区三区精彩视频 | 国产欧美久久久久久 | 不卡一区 | 日本久久久 | av网站大全免费 | 91人人| 永久黄网站色视频免费观看w | 欧美视频免费在线 | 自拍偷拍亚洲欧美 | 不卡免费在线视频 | 天天干夜夜爽 | 国产噜噜噜噜噜久久久久久久久 | 中文字幕久久精品 | 中文字幕在线免费看 | 亚洲国产精品99久久久久久久久 | 亚洲欧美日韩精品久久亚洲区 | 午夜伦理影院 | 欧美一区二区三区在线观看视频 | 欧美九九 | 永久91嫩草亚洲精品人人 | 精品在线一区二区 | 久久久久国产一区二区三区 |