Object是所有類的父類,也就是說java/236257.html">java中所有的類都是直接或者間接繼承自O(shè)bject類。比如你隨便創(chuàng)建一個classA,雖然沒有明說,但默認是extendsObject的。
后面的三個點"..."表示可以接受若干不確定數(shù)量的參數(shù)。老的寫法是Objectargs[]這樣,但新版本的java中推薦使用...來表示。例如
	publicvoidgetSomething(String...strings)(){}
object是java中所有類的父類,也就是說所有的類,不管是自己創(chuàng)建的類還是系統(tǒng)中的類都繼承自object類,也就是說所有的類在任何場合都可以代替object類,根據(jù)里氏替換原則,子類在任何場合都可以代替其父類,而父類卻不一定能代替其子類,java中常說的萬物皆對象說的其實就是這個道理!object類體現(xiàn)了oop思想中的多態(tài),繼承,封裝,抽象四大特性!
object類是所有類的基類,不是數(shù)據(jù)類型。這個你可以查詢jdk文檔了解,所有類都繼承自O(shè)bject。
Object...objects這種參數(shù)定義是在不確定方法參數(shù)的情況下的一種多態(tài)表現(xiàn)形式。即這個方法可以傳遞多個參數(shù),這個參數(shù)的個數(shù)是不確定的。這樣你在方法體中需要相應(yīng)的做些處理。因為Object是基類,所以使用Object...objects這樣的參數(shù)形式,允許一切繼承自O(shè)bject的對象作為參數(shù)。這種方法在實際中應(yīng)該還是比較少用的。
Object[]obj這樣的形式,就是一個Object數(shù)組構(gòu)成的參數(shù)形式。說明這個方法的參數(shù)是固定的,是一個Object數(shù)組,至于這個數(shù)組中存儲的元素,可以是繼承自O(shè)bject的所有類的對象。
這些基礎(chǔ)東西建議你多看幾遍"Thinkinjava"
Java的Object是所有其他類的父類,從繼承的層次來看它就是最頂層根,所以它也是唯一一個沒有父類的類。它包含了對象常用的一些方法,比如getClass、hashCode、equals、clone、toString、notify、wait等常用方法。所以其他類繼承了Object后就可以不用重復實現(xiàn)這些方法。這些方法大多數(shù)是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方法
由于registerNatives方法被static塊修飾,所以在加載Object類時就會執(zhí)行該方法,對應(yīng)的本地方法為Java_java_lang_Object_registerNatives,如下,
JNIEXPORT void JNICALLJava_java_lang_Object_registerNatives(JNIEnv *env, jclass cls){	(*env)->RegisterNatives(env, cls,	methods, sizeof(methods)/sizeof(methods[0]));}可以看到它間接調(diào)用了JNINativeInterface_結(jié)構(gòu)體的方法,簡單可以看成是這樣:它干的事大概就是將Java層的方法名和本地函數(shù)對應(yīng)起來,方便執(zhí)行引擎在執(zhí)行字節(jié)碼時根據(jù)這些對應(yīng)關(guān)系表來調(diào)用C/C++函數(shù),如下面,將這些方法進行注冊,執(zhí)行引擎執(zhí)行到hashCode方法時就可以通過關(guān)系表來查找到JVM的JVM_IHashCode函數(shù),其中()I還可以得知Java層上的類型應(yīng)該轉(zhuǎn)為int類型。這個映射其實就可以看成將字符串映射到函數(shù)指針。
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方法也是個本地方法,對應(yīng)的本地方法為Java_java_lang_Object_getClass,如下:
JNIEXPORT jclass JNICALLJava_java_lang_Object_getClass(JNIEnv *env, jobject this){  if (this == NULL) {    JNU_ThrowNullPointerException(env, NULL);    return 0;  } else {    return (*env)->GetObjectClass(env, this);  }}所以這里主要就是看GetObjectClass函數(shù)了,Java層的Class在C++層與之對應(yīng)的則是klassOop,所以關(guān)于類的元數(shù)據(jù)和方法信息可以通過它獲得。
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_ENDhashCode方法
由前面registerNatives方法將幾個本地方法注冊可知,hashCode方法對應(yīng)的函數(shù)為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函數(shù)決定,實現(xiàn)比較復雜,根據(jù)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;}equals方法
這是一個非本地方法,判斷邏輯也十分簡單,直接==比較。
clone方法
由本地方法表知道clone方法對應(yīng)的本地函數(shù)為JVM_Clone,clone方法主要實現(xiàn)對象的克隆功能,根據(jù)該對象生成一個相同的新對象(我們常見的類的對象的屬性如果是原始類型則會克隆值,但如果是對象則會克隆對象的地址)。Java的類要實現(xiàn)克隆則需要實現(xiàn)Cloneable接口,if (!klass->is_cloneable())這里會校驗是否有實現(xiàn)該接口。然后判斷是否是數(shù)組分兩種情況分配內(nèi)存空間,新對象為new_obj,接著對new_obj進行copy及C++層數(shù)據(jù)結(jié)構(gòu)的設(shè)置。最后再轉(zhuǎn)成jobject類型方便轉(zhuǎn)成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_ENDtoString方法
邏輯是獲取class名稱加上@再加上十六進制的hashCode。
notify方法
此方法用來喚醒線程,final修飾說明不可重寫。與之對應(yīng)的本地方法為JVM_MonitorNotify,ObjectSynchronizer::notify最終會調(diào)用ObjectMonitor::notify(TRAPS),這個過程是ObjectSynchronizer會嘗試當前線程獲取freeObjectMonitor對象,不成功則嘗試從全局中獲取。
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_ENDObjectMonitor對象包含一個_WaitSet隊列對象,此對象保存著所有處于wait狀態(tài)的線程,用ObjectWaiter對象表示。notify要做的事是先獲取_WaitSet隊列鎖,再取出_WaitSet隊列中第一個ObjectWaiter對象,再根據(jù)不同策略處理該對象,比如把它加入到_EntryList隊列中。然后再釋放_WaitSet隊列鎖。它并沒有釋放synchronized對應(yīng)的鎖,所以鎖只能等到synchronized同步塊結(jié)束時才釋放。
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方法是讓線程等待,它對應(yīng)的本地方法是JVM_MonitorWait,間接調(diào)用了ObjectSynchronizer::wait,與notify對應(yīng),它也是對應(yīng)調(diào)用ObjectMonitor對象的wait方法。該方法較長,這里不貼出來了,大概就是創(chuàng)建一個ObjectWaiter對象,接著獲取_WaitSet隊列鎖將ObjectWaiter對象添加到該隊列中,再釋放隊列鎖。另外,它還會釋放synchronized對應(yīng)的鎖,所以鎖沒有等到synchronized同步塊結(jié)束時才釋放。
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_ENDfinalize方法
這個方法用于當對象被回收時調(diào)用,這個由JVM支持,Object的finalize方法默認是什么都沒有做,如果子類需要在對象被回收時執(zhí)行一些邏輯處理,則可以重寫finalize方法
總結(jié)
以上就是本文關(guān)于Java從JDK源碼角度對Object進行實例分析的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
新聞熱點
疑難解答
圖片精選