Java从JDK源码角度对Object进行实例分析
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 {}}
JNIEXPORT void JNICALLJava_java_lang_Object_registerNatives(JNIEnv *env, jclass cls){(*env)->RegisterNatives(env, cls,methods, sizeof(methods)/sizeof(methods[0]));}
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,如下:
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函数了,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
hashCode方法
由前面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 NULLreturn 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() ;} elseif (hashCode == 1) {intptr_t addrBits = intptr_t(obj) >> 3 ;value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;} elseif (hashCode == 2) {value = 1 ;// for sensitivity testing} elseif (hashCode == 3) {value = ++GVars.hcSequence ;} elseif (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方法
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对象,不成功则尝试从全局中获取。
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 EntryListif (List == NULL) {iterator->_next = iterator->_prev = NULL ;_EntryList = iterator ;} else {List->_prev = iterator ;iterator->_next = List ;iterator->_prev = NULL ;_EntryList = iterator ;}} elseif (Policy == 1) {// append to EntryListif (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 ;}} elseif (Policy == 2) {// prepend to cxq// prepend to cxqif (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 ;}}}} elseif (Policy == 3) {// append to cxqiterator->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() ;}}
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
