Object是所有類別的父類,也就是說java中所有的類別都是直接或間接繼承自Object類別。例如你隨便建立一個class A,雖然沒有明說,但預設是extends Object的。
後面的三個點"..."表示可以接受若干不確定數量的參數。老的寫法是Object args[]這樣,但新版本的java推薦使用 ...來表示。例如
public void getSomething(String ... strings)(){}
object 是java中所有類別的父類,也就是說所有的類,不管是自己創建的類別還是系統中的類別都繼承自object類,也就是說所有的類別在任何場合都可以代替object類,根據里氏替換原則,子類在任何場合都可以代替其父類,而父類卻不一定能代替其子類,java中常說的萬物皆對象說的其實就是這個道理! object類別體現了oop思想中的多態,繼承,封裝,抽象四大特性!
object類別是所有類別的基底類,不是資料類型。這個你可以查詢jdk文件了解,所有類別都繼承自Object。
Object ...objects這種參數定義是在不確定方法參數的情況下的一種多型表現。即這個方法可以傳遞多個參數,而這個參數的數量是不確定的。這樣你在方法體中需要相對應的做些處理。因為Object是基底類,所以使用Object ...objects這樣的參數形式,允許一切繼承自Object的物件作為參數。這種方法在實際中應該還是比較少用的。
Object[] obj這樣的形式,就是一個Object陣列所構成的參數形式。說明這個方法的參數是固定的,是一個Object數組,至於這個數組中儲存的元素,可以是繼承自Object的所有類別的物件。
這些基礎東西建議你多看幾遍"Think in java"
Java的Object是所有其他類別的父類,從繼承的層次來看它就是最頂層根,所以它也是唯一一個沒有父類別的類別。它包含了物件常用的一些方法,例如getClass
、hashCode
、equals
、clone
、toString
、 notify
、wait
等常用方法。所以其他類別繼承了Object後就可以不用重複實作這些方法。這些方法大多是native方法,下面具體分析。
主要的程式碼如下:
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方法被static區塊修飾,所以在載入Object類別時就會執行該方法,對應的本地方法為Java_java_lang_Object_registerNatives
,如下,
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型別。這個映射其實可以看成將字串映射到函數指標。
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方法也是個本地方法,對應的本地方法為Java_java_lang_Object_getClass
,如下:
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
,所以關於類別的元資料和方法資訊可以透過它來獲得。
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
由前面registerNatives方法將幾個本地方法註冊可知,hashCode方法對應的函數為JVM_IHashCode
,即
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遮罩處理。
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; }
這是一個非本地方法,判斷邏輯也十分簡單,直接==比較。
由本地方法表知道clone方法對應的本地函數為JVM_Clone
,clone方法主要實現物件的克隆功能,根據該物件產生一個相同的新物件(我們常見的類別的物件的屬性如果是原始類型則會複製值,但如果是物件則會複製物件的位址)。 Java的類別要實作複製則需要實作Cloneable接口,if (!klass->is_cloneable())
這裡會校驗是否有實作該介面。然後判斷是否為陣列分兩種情況分配記憶體空間,新物件為new_obj,接著對new_obj進行copy及C++層資料結構的設定。最後再轉成jobject型別方便轉成Java層的Object型別。
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
邏輯是取得class名稱加上@再加上十六進位的hashCode。
此方法用来唤醒线程,final修饰说明不可重写。与之对应的本地方法为JVM_MonitorNotify
,ObjectSynchronizer::notify
最终会调用ObjectMonitor::notify(TRAPS)
,这个过程是ObjectSynchronizer会尝试当前线程获取free ObjectMonitor对象,不成功则尝试从全局中获取。
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同步块结束时才释放。
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() ; } }
与notify方法类似,只是在取_WaitSet
队列时不是取第一个而是取所有。
wait方法是让线程等待,它对应的本地方法是JVM_MonitorWait
,间接调用了ObjectSynchronizer::wait
,与notify对应,它也是对应调用ObjectMonitor对象的wait方法。该方法较长,这里不贴出来了,大概就是创建一个ObjectWaiter对象,接着获取_WaitSet
队列锁将ObjectWaiter对象添加到该队列中,再释放队列锁。另外,它还会释放synchronized对应的锁,所以锁没有等到synchronized同步块结束时才释放。
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
这个方法用于当对象被回收时调用,这个由JVM支持,Object的finalize方法默认是什么都没有做,如果子类需要在对象被回收时执行一些逻辑处理,则可以重写finalize方法。
以上是Java從JDK源碼角度看Object的實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!