Objek adalah kelas induk dari semua kelas, yaitu, semua kelas di Java diwarisi secara langsung atau tidak langsung dari kelas objek. Misalnya, jika Anda membuat classa, meskipun tidak secara eksplisit dinyatakan, itu adalah default dari ExtendSObject.
Tiga poin berikut "..." menunjukkan bahwa beberapa parameter yang tidak pasti dapat diterima. Cara menulis lama adalah ObjectArgs [], tetapi disarankan untuk menggunakan ... dalam versi baru Java. Misalnya
publicvoidgetSomething(String...strings)(){}
Objek adalah kelas induk dari semua kelas di Java. Dengan kata lain, semua kelas, apakah mereka dibuat sendiri atau kelas dalam sistem, diwarisi dari kelas objek, yaitu, semua kelas dapat menggantikan kelas objek dalam setiap kesempatan. Menurut prinsip penggantian Rich, subclass dapat menggantikan kelas induknya dalam setiap kesempatan, tetapi kelas induk mungkin tidak harus menggantikan subclass mereka. Apa yang sering dikatakan di Java sebenarnya adalah kebenaran ini! Kelas objek mewujudkan empat karakteristik utama polimorfisme, warisan, enkapsulasi, dan abstraksi dalam ide OOP!
Kelas objek adalah kelas dasar dari semua kelas, bukan tipe data. Anda dapat meminta dokumen JDK untuk memahami hal ini, semua kelas diwarisi dari objek.
Objek ... Objek Definisi parameter ini adalah manifestasi polimorfik dalam kasus parameter metode yang tidak pasti. Artinya, metode ini dapat melewati beberapa parameter, dan jumlah parameter ini tidak pasti. Dengan cara ini, Anda perlu melakukan beberapa pemrosesan yang sesuai di badan metode. Karena objek adalah kelas dasar, gunakan bentuk parameter seperti objek ... objek, memungkinkan semua objek yang diwarisi dari objek sebagai parameter. Metode ini harus digunakan secara relatif jarang dalam praktik.
Bentuk objek [] OBJ adalah bentuk parameter yang terdiri dari array objek. Ini berarti bahwa parameter metode ini diperbaiki dan merupakan array objek. Adapun elemen yang disimpan dalam array ini, mereka dapat menjadi objek yang diwarisi dari semua kelas objek.
Disarankan agar Anda membaca hal -hal dasar ini beberapa kali lagi "thinkinjava"
Objek Java adalah kelas induk dari semua kelas lainnya. Dari perspektif warisan, itu adalah akar tingkat atas, jadi itu juga satu-satunya kelas tanpa kelas induk. Ini berisi beberapa metode yang umum digunakan untuk objek, seperti GetClass, HashCode, Equals, Clone, Tostring, Notify, Wait dan metode lain yang umum digunakan. Oleh karena itu, setelah kelas lain mewarisi objek, mereka dapat mengimplementasikan metode ini tanpa implementasi berulang. Sebagian besar metode ini adalah metode asli, dan analisis terperinci berikut dibuat.
Kode utamanya adalah sebagai berikut:
objek kelas publik {private static asli void registernatives (); static {registernatives ();} Public Final Native Class <?> getClass (); public native int hashCode (); public boolean setara (objek obj) {return (this == obj);} public tosire native clone clone () melempar clonceporporporported excepting public; 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 ("Nilai batas waktu adalah negatif");} if (nanos <0 || nanos> 999999) {lempar baru ilegalargumentException ("Nanos Nilai Timeout Kedua di luar jangkauan");} if (nanos> 0) {timeout ++;} tunggu (timeout); {tunggu (0);} void finalisasi yang dilindungi () melempar lempar {}}metode registernatif
Karena metode registernatif dimodifikasi oleh blok statis, metode ini akan dieksekusi ketika kelas objek dimuat. Metode lokal yang sesuai adalah java_java_lang_object_registernatives, sebagai berikut,
Jniexport void jnicalljava_java_lang_object_registernatives (jnienv *env, jclass cls) {( *env)-> registernatives (env, cls, metode, sizeof (metode)/sizeof (metode [0]));}Anda dapat melihat bahwa secara tidak langsung memanggil metode struktur JninativeInterface_, yang dapat dengan mudah dianggap sebagai ini: apa yang dilakukannya mungkin sesuai dengan nama metode lapisan Java dengan fungsi lokal, sehingga mesin eksekusi dapat memanggil fungsi C/C ++ berdasarkan tabel hubungan yang sesuai ketika menjalankan bytecode. Seperti yang ditunjukkan di bawah ini, daftarkan metode ini. Ketika mesin eksekusi menjalankan metode kode hash, dapat menemukan fungsi JVM_IHashCode JVM melalui tabel hubungan. () Saya juga bisa tahu bahwa jenis pada lapisan java harus dikonversi menjadi tipe int. Pemetaan ini sebenarnya dapat dianggap memetakan string ke penunjuk fungsi.
Statis JninativeMethod Metode [] = {{"hashCode", "() i", (void *) & jvm_ihashCode}, {"tunggu", "(j) v", (void *) & jvm_monitorWait}, {"notify", "() void *), void *) {void *), {" notify "," () void *), {void *), {void *), {void *), {void *), {void *), " "() V", (void *) & jvm_monitornotifyall}, {"clone", "() ljava/lang/objek;", (void *) & jvm_clone},}; Metode GetClass
Metode getClass juga merupakan metode lokal, dan metode lokal yang sesuai adalah java_java_lang_object_getclass, sebagai berikut:
Jniexport JClass Jnicalljava_java_lang_object_getClass (jnienv *env, jobject ini) {if (this == null) {jnu_thrownullpointerexception (env, null); kembali 0; } else {return (*env)-> getObjectClass (env, this); }}Jadi di sini kita terutama melihat fungsi GetObjectClass. Kelas yang sesuai di lapisan java di lapisan C ++ adalah klassoop, sehingga metadata dan informasi metode tentang kelas dapat diperoleh melalui itu.
Jni_entry (jclass, jni_getobjectclass (jnienv *env, pekerjaan 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_endmetode kode hash
Dari metode registernatif sebelumnya mendaftarkan beberapa metode lokal, kita dapat melihat bahwa fungsi yang sesuai dengan metode kode hashcode adalah jvm_ihashcode, yaitu,
Jvm_entry (jint, jvm_ihashcode (jnienv* env, handle pekerjaan)) jvmwrapper ("jvm_ihashcode"); // seperti yang diimplementasikan dalam mesin virtual klasik; return 0 jika objek adalah null return handle == null? 0: ObjectSynchronizer :: fasthashCode (Thread, JNIhandles :: resolve_non_null (handle)); jvm_endLogika yang dihasilkan untuk kode hash ditentukan oleh fungsi get_next_hash dari synchronizer.cpp. Implementasinya relatif kompleks. Ada berbagai strategi generasi berdasarkan nilai hashcode yang berbeda, dan akhirnya mask hash digunakan untuk memprosesnya.
statis inline intptr_t get_next_hash (thread * self, oop obj) {intptr_t value = 0; if (hashcode == 0) {value = os :: random ();} lain jika (hashcode == 1) {intptr_t addrbits = intptr_t (hashcode) {intptr_t addrbits = intptr_t (obj) == 1) {intptr_t addrbits = intptr_t (Obj) >> Gvars.stwrandom;} lain jika (hashcode == 2) {value = 1; // untuk pengujian sensitivitas} lain jika (hashcode == 3) {value = ++ gvars.hcSequence;} lain jika (hashcode == 4) {value = intptr_t (obj);} lain << 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, "invarian"); tevent (hashcode: menghasilkan); nilai pengembalian;} sama dengan metode
Ini adalah metode non-lokal, dan logika penilaian sangat sederhana, dan secara langsung == Perbandingan.
metode klon
Dari tabel metode lokal, kita tahu bahwa fungsi lokal yang sesuai dengan metode klon adalah jvm_clone. Metode klon terutama mengimplementasikan fungsi kloning dari objek dan menghasilkan objek baru yang sama berdasarkan objek (atribut objek kelas umum kita akan mengkloning nilai jika itu adalah tipe primitif, tetapi jika itu adalah objek, alamat objek akan dikloning). Untuk mengimplementasikan kloning kelas Java, Anda perlu menerapkan antarmuka yang dapat dikloning. If (! Klass-> is_clonable ()) akan memverifikasi apakah antarmuka diimplementasikan. Kemudian tentukan apakah ruang memori dialokasikan dalam dua situasi. Objek baru adalah new_obj, dan kemudian menyalin dan struktur data lapisan C ++ diatur untuk new_obj. Akhirnya, itu akan dikonversi ke jenis pekerjaan ke tipe objek Java Layer.
Jvm_entry (Jobject, jvm_clone (jnienv* env, handle pekerjaan)) jvmwrapper ("jvm_clone"); handle obj (thread, jnihandles :: resolve_non_null (handle)); const Klashandle klass (thread, obj- Klass (); (!!! {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_RITE_REPT (), "BARRIER (); 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_endMetode Tostring
Logikanya adalah untuk mendapatkan nama kelas plus @ plus hexadecimal hashcode.
Beri tahu metode
Metode ini digunakan untuk membangunkan utas, dan instruksi modifikasi akhir tidak dapat ditulis ulang. Metode lokal yang sesuai adalah JVM_Monitornotify. ObjectSynchronizer :: Notify pada akhirnya akan memanggil ObjectMonitor :: Notify (Traps). Proses ini adalah bahwa ObjectSynchronizer akan mencoba mendapatkan objek FreeObjectMonitor di utas saat ini, dan mencoba mendapatkannya dari global jika gagal.
Jvm_entry (void, jvm_monitornotify (jnienv* env, handle pekerjaan)) jvmwrapper ("jvm_monitornotify"); Tangani OBJ (Thread, JNIhandles :: resolve_non_null (handle)); Assert (obj-> is_instance () || obj-> is_array (), "jvm_monitornotify harus berlaku untuk suatu objek"); ObjectSynchronizer :: Notify (OBJ, periksa); Jvm_endObjek ObjectMonitor berisi objek antrian _waitset, yang menampung semua utas dalam keadaan tunggu dan diwakili oleh objek ObjectWaiter. Yang perlu dilakukan untuk dilakukan adalah terlebih dahulu mendapatkan kunci antrian _waitset, kemudian hapus objek Objectwaaiter pertama dalam antrian _waitset, dan kemudian memproses objek sesuai dengan strategi yang berbeda, seperti menambahkannya ke antrian _entrylist. Kemudian lepaskan kunci antrian _waitset. Itu tidak melepaskan kunci yang sesuai dari sinkronisasi, sehingga kunci hanya dapat dilepaskan sampai blok sinkronisasi yang disinkronkan selesai.
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 = dequeewaaiter (); if (iterator! = null) {tevent (notify1-transfer); jaminan (iterator-> tState == objectwaaiter :: ts_wait, "invarian"); jaminan (iterator-> _ notified == 0, "invarian"); if (polion! ObjectWaiter :: ts_enter;} iterator-> _ notify = 1; ObjectWaiter * list = _entrylist; if (list! = Null) {assert (list-> _ prev == null, "invariant"); assert (list-> tState == objectwaiter :: ts_enter "); ungkapan); list"; tstate == Objectwaiter :: ts_enter "); ungkapan) (list-> tState == Objectwaiter :: ts_enter"); ;} if (policy == 0) {// prepend ke entrylistif (list == null) {iterator-> _ next = iterator-> _ prev = iterator;} else {list-> _ prev = iterator; tererator-> _ next = list; iterator-> _ prev = null; _entry-> _ next = list; iterator-> _ prev = null; _Ertry; Tambahkan ke EntryListif (list == null) {iterator-> _ NEXT = iterator-> _ prev = null; _entrylist = iterator;} else {// Pertimbangkan: Menemukan ekor saat ini membutuhkan jalan waktu linier // daftar entri. Kita dapat membuat akses-waktu konstanta dengan mengonversi ke // cdll alih-alih menggunakan dll.ObjectWaiter * kami saat ini * tail; for (tail = list; tail-> _ next! = Null; tail = tail-> _ next); assert (tail! = Null && tail-> _ next == null, "invariant"); tail-> _ tail = _ next == null, "invariant"); tail-> _ tail = _ next == null, "invarian"); tail-> _ tail = _ next == null, "invariant")); tail-_ _ _ _ _ next == null, "Invariant")); tail-_ _ _ _ _ next == null, "Invariant"); tail-> _ _ _ _ _ _ next == null, "invariant"); _ _ _ ; Iterator-> _ NEXT = NULL;}} lain jika (policy == 2) {// prepend ke cxq // prepend to cxqif (list == null) {iterator-> _ next = iterator-> _ prev = null; _entrylist = iterator;} lain {iterator-> null; _entrylist = iterator;} lain {iterator-> tax: _entrylist = iterator;} lain {iterator-> {ObjectWaiter * front = _cxq; iterator-> _ next = front; if (atomic :: cmpxchg_ptr (iterator, & _cxq, front) == depan) {break;}}} lain jika (kebijakan == 3) {// tambahkan cxqiter->; {ObjectWaiter * tail; tail = _cxq; if (tail == null) {iterator-> _ next = null; if (atomic :: cmpxchg_ptr (iterator, & _cxq, null) == null) {break;}} else {while while (_cxq, _ next! =-Null) {break;}} else {while while (_cxq, _ next! ; iterator-> _ prev = tail; iterator-> _ next = null; break;}}} else {parkeVent * ev = iterator-> _ event; iterator-> tState = ObjectWaiter :: ts_run; orderaccess :: pagar (); ev-> unpark ();} IF; {iterator-> wait_reenter_begin (this);} // _waitsetlock melindungi antrian tunggu, bukan daftar masuk. Kami dapat // memindahkan operasi add-to-entrylist, di atas, di luar bagian kritis // dilindungi oleh _waitsetlock. Dalam praktiknya itu tidak berguna. Dengan // pengecualian tunggu () waktu tunggu dan mengganggu pemilik monitor // adalah satu -satunya utas yang meraih _waitsetlock. Hampir tidak ada konten // di _waitsetlock sehingga tidak menguntungkan untuk mengurangi panjang // bagian kritis.} Thread :: spinrelease (& _waitsetlock); if (iterator! = Null && objectMonitor :: _ sync_notification! = Null) {ObjectMonitor :: _ Sync_noTiCations;Metode NotifyAll
Mirip dengan metode notify, hanya saja ketika mengambil antrian _waitset, itu bukan yang pertama tetapi semua.
Metode tunggu
Metode tunggu membuat utas menunggu. Metode lokal yang sesuai adalah JVM_MonitorWait, yang secara tidak langsung disebut ObjectSynchronizer :: Wait, yang sesuai dengan notify. Ini juga merupakan metode tunggu yang sesuai dengan memanggil objek ObjectMonitor. Metode ini panjang dan tidak akan diposting di sini. Ini mungkin untuk membuat objek ObjectWaiter, kemudian dapatkan kunci antrian _waitset dan tambahkan objek Objectwaaiter ke antrian, dan kemudian lepaskan kunci antrian. Selain itu, akan melepaskan kunci yang sesuai dari sinkronisasi, sehingga kunci tidak menunggu sampai blok sinkronisasi yang disinkronkan selesai.
Jvm_entry (void, jvm_monitorwait (jnienv* env, pegangan pekerjaan, jlong ms)) jvmwrapper ("jvm_monitorwait"); Tangani OBJ (Thread, JNIhandles :: resolve_non_null (handle)); Assert (obj-> is_instance () || obj-> is_array (), "jvm_monitorwait harus berlaku untuk objek"); JavathreadinObjectwaitstate jTiows (thread, ms! = 0); if (jvmtiExport :: harus_post_monitor_wait ()) {jvmtiExport :: post_monitor_wait ((javathread *) utas, (oop) obj (), ms); } ObjectSynchronizer :: tunggu (obj, ms, periksa); jvm_endFinalisasi metode
Metode ini digunakan untuk dipanggil saat objek didaur ulang. Ini didukung oleh JVM. Metode finalisasi objek tidak melakukan apa pun secara default. Jika subclass perlu melakukan beberapa pemrosesan logis ketika objek didaur ulang, metode finalisasi dapat ditimpa.
Meringkaskan
Di atas adalah semua konten dari artikel ini tentang contoh analisis objek Java dari perspektif kode sumber JDK. Saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!