Objekt ist die übergeordnete Klasse aller Klassen, dh alle Klassen in Java werden direkt oder indirekt von der Objektklasse geerbt. Wenn Sie beispielsweise eine Klasse erstellen, obwohl sie nicht explizit angegeben ist, ist dies die Standardeinstellung von ExtendsObject.
Die folgenden drei Punkte "..." geben an, dass mehrere unsichere Anzahl von Parametern akzeptiert werden können. Die alte Art des Schreibens ist ObjektArgs [], aber es wird empfohlen, ... in der neuen Version von Java zu verwenden. Zum Beispiel
publicvoidgetSomething(String...strings)(){}
Objekt ist die übergeordnete Klasse aller Klassen in Java. Das heißt, alle Klassen, unabhängig davon, ob sie von sich selbst oder den Klassen im System erstellt werden, werden von der Objektklasse geerbt, dh alle Klassen können die Objektklasse in jeder Gelegenheit ersetzen. Nach dem Prinzip von Richs Ersatz können Unterklassen ihre Elternklasse in jeder Gelegenheit ersetzen, aber die übergeordnete Klasse ersetzt möglicherweise nicht unbedingt ihre Unterklasse. Was in Java oft gesagt wird, ist eigentlich diese Wahrheit! Die Objektklasse verkörpert die vier Hauptmerkmale des Polymorphismus, der Vererbung, der Einkapselung und der Abstraktion in der OOP -Idee!
Die Objektklasse ist die Basisklasse aller Klassen, kein Datentyp. Sie können das JDK -Dokument abfragen, um dies zu verstehen. Alle Klassen werden vom Objekt geerbt.
Objekt ... Objekte Diese Parameterdefinition ist eine polymorphe Manifestation bei unsicheren Methodenparametern. Das heißt, diese Methode kann mehrere Parameter übergeben, und die Anzahl dieser Parameter ist ungewiss. Auf diese Weise müssen Sie eine entsprechende Verarbeitung im Methode -Körper durchführen. Da Objekt eine Basisklasse ist, verwenden Sie Parameterform wie Objekte ... Objekte, sodass alle Objekte, die von Objekten als Parameter geerbt wurden. Diese Methode sollte in der Praxis relativ selten angewendet werden.
Die Form von Objekt [] OBJ ist eine Parameterform, die aus einem Objektarray besteht. Dies bedeutet, dass die Parameter dieser Methode festgelegt sind und ein Objektarray sind. Was die in diesem Array gespeicherten Elemente betrifft, können sie Objekte sein, die von allen Objektklassen geerbt wurden.
Es wird empfohlen, diese grundlegenden Dinge noch ein paar Mal "Thinkinjava" zu lesen.
Javas Objekt ist die übergeordnete Klasse aller anderen Klassen. Aus der Perspektive der Vererbung ist es die Wurzel der obersten Ebene, daher ist es auch die einzige Klasse ohne übergeordnete Klasse. Es enthält einige häufig verwendete Methoden für Objekte, wie GetClass, Hashcode, Gleiche, Klon, Tostring, Benachrichtigung, Warten und andere häufig verwendete Methoden. Nachdem andere Klassen das Objekt erben, können sie diese Methoden ohne wiederholte Implementierung implementieren. Die meisten dieser Methoden sind native Methoden, und die folgende detaillierte Analyse wird durchgeführt.
Der Hauptcode lautet wie folgt:
public class -Objekt {private statische native void RegisterNatives (); static {RegisterNatives ();} öffentliche native Klasse <?> getClass (); public native int hashcode (); public boolean gleichen gleich + "@" + Integer negativ ");} if (nanos <0 || nanos> 999999) {Wirf neu illegalArgumentException (" Nanos zweiter Zeitout -Wert außerhalb des Bereichs ");} if (nanos> 0) {Timeout ++;} Wartezeit (Zeitout);} öffentliche endgültige void -abschließend () Thrungen. {}}METHODE METHODE
Da die Methode RegisterNatives durch einen statischen Block geändert wird, wird die Methode ausgeführt, wenn die Objektklasse geladen wird. Die entsprechende lokale Methode ist wie folgt java_java_lang_object_registerNatives.
Jniexport void jnicalljava_java_lang_object_registerNatives (jnienv *env, jclass cls) {( *env)-> Registernativen (Env, Cls, Methoden, Methoden (Methoden)/Größe (Methoden [0]);}Sie können sehen, dass es indirekt die Methode der Struktur von JninativeInterface_ aufruft, die einfach so angesehen werden kann: Was sie tut, entspricht wahrscheinlich dem Methodennamen der Java -Schicht mit der lokalen Funktion, so dass die Ausführungs -Engine C/C ++ -Funktionen basierend auf diesen entsprechenden Beziehungstabellen bei der Ausführung von Bytecode aufrufen kann. Registrieren Sie diese Methoden, wie unten gezeigt. Wenn die Ausführungs -Engine die HashCode -Methode ausführt, finden Sie die JVM -Funktion der JVM JVM_IHashCode über die Beziehungstabelle. () Ich kann auch wissen, dass die Typen auf der Java -Schicht in den Typ in INT konvertiert werden sollten. Diese Zuordnung kann tatsächlich als Zuordnung einer Zeichenfolge zu einem Funktionszeiger angesehen werden.
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/Objekt;", (void *) & jvm_clone},}; GetClass -Methode
Die GetClass -Methode ist auch eine lokale Methode, und die entsprechende lokale Methode ist wie folgt Java_Java_lang_object_getClass:
Jniexport jclass jnicalljava_java_lang_object_getClass (jnienv *env, jobject that that that that) {if (this == null) {jnu_thrownullpointerexception (env, null); Rückkehr 0; } else {return (*env)-> getObjectClass (env, this); }}Hier schauen wir uns also hauptsächlich die GetObjectClass -Funktion an. Die entsprechende Klasse in der Java -Schicht in der C ++ - Schicht ist KLASSOOP, sodass die Metadaten- und Methodeninformationen zur Klasse durch sie erhalten werden können.
Jni_entry (jclass, jni_getObjectClass (jnienv *env, Job obj)) jniwrapper ("getObjectClass"); DTRACE_PROBE2 (hotspot_jni, getObjectClass__entry, env, obj); Klasoop 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); ret zurück; jni_endHashcode -Methode
Aus den vorherigen RegisterNatives -Methoden wird mehrere lokale Methoden registriert. Wir können sehen, dass die Funktion, die der HashCode -Methode entspricht, JVM_IHashCode ist, dh.
JVM_ENTRY (jint, jvm_ihashcode (jnienv* env, Job Handle)) JVMWrapper ("JVM_IHashCode"); // wie in der klassischen virtuellen Maschine implementiert; Rückgabe 0 Wenn das Objekt NULL Returnhandle == NULL ist? 0: ObjectSynchronizer :: FasthashCode (Thread, JniHandles :: Resolve_non_null (Handle)); jvm_endDie für HashCode generierte Logik wird durch die Funktion get_next_hash von synchronizer.cpp bestimmt. Die Implementierung ist relativ komplex. Es gibt verschiedene Generationsstrategien, die auf verschiedenen Werten von HashCode basieren, und schließlich wird eine Hash -Maske verwendet, um sie zu verarbeiten.
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; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 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; unsigniertes v = self-> _ Hashstatew; ; Self-> _ HashStatew = v; value = v;} Wert & = markoopDesc :: Hash_mask; if (value == 0) value = 0xBad; Gleiche Methode
Dies ist eine nicht lokale Methode, und die Urteilslogik ist sehr einfach und es ist direkt == Vergleich.
Klonmethode
Aus der lokalen Methode Tabelle wissen wir, dass die lokale Funktion, die der Klonmethode entspricht, JVM_CLone ist. Die Klonmethode implementiert hauptsächlich die Klonierungsfunktion des Objekts und generiert das gleiche neue Objekt basierend auf dem Objekt (die Attribute des Objekts unserer gemeinsamen Klasse klonen den Wert, wenn es sich um einen primitiven Typ handelt. Wenn es sich jedoch um ein Objekt handelt, wird die Adresse des Objekts geklont). Um das Klonen von Java -Klassen zu implementieren, müssen Sie die klonbare Schnittstelle implementieren. If (! Klass-> is_clonable ()) prüft, ob die Schnittstelle implementiert ist. Bestimmen Sie dann, ob der Speicherraum in zwei Situationen zugewiesen wird. Das neue Objekt ist New_Obj und dann kopieren und C ++ - Schichtdatenstruktur werden für new_obj gesetzt. Schließlich wird es in den Jobtyp in den Java -Layer -Objekttyp umgewandelt.
JVM_ENTRY (Jobject, jvm_clone (jnienv* env, Job-Handle)) JVMWrapper ("JVM_Clone"); Handle OBJ (Thread, JniHandles :: Resolve_Non_null (Handle)); const klasshandle kLass (thread, obj-> klass (); . {const int length = ((Arrayoop) obj ())-> length (); new_obj = collectedheap :: array_allocation (klass, Größe, Länge, check_null);} else {new_obj = collectedDeap :: obj_allocation (klass, check_null). (jlong*) new_obj, (size_t) align_object_size (size) / heapwordsperlong); new_obj-> init_mark (); barrieret* bs = universe :: heap ()-> barrier_set (); write_region "); bs-> write_region (memregion ((heapword*) new_obj, Größe)); if (klass-> has_finalizer ()) {assert (obj-> is_instance ()," sollte Instanceoop sein "); new_obj = InstanceKLass :: Register_Final (Instanceoop (New_Obj. JniHandles :: make_local (env, oop (new_obj)); jvm_endTOString -Methode
Die Logik besteht darin, den Klassennamen plus @ plus hexadezimales Hashcode zu erhalten.
Methode benachrichtigen
Diese Methode wird verwendet, um den Thread aufzuwecken, und die endgültigen Änderungsanweisungen können nicht umgeschrieben werden. Die entsprechende lokale Methode ist JVM_Monitornotify. ObjectSynchronizer :: Benachrichtigen rufen irgendwann ObjectMonitor :: Benachrichtigung (Fallen) auf. Dieser Vorgang ist, dass ObjectSynchronizer versucht, das FreeObjectMonitor -Objekt in den aktuellen Thread zu erhalten und es aus dem globalen Global zu erhalten, wenn es fehlschlägt.
Jvm_entry (void, jvm_monitornotify (jnienv* env, Job Handle)) JVMWrapper ("JVM_Monitornotify"); Handle OBJ (Thread, jniHandles :: Resolve_Non_null (Handle)); assert (obj-> is_instance () || obj-> is_array (), "jvm_monitornotify muss für ein Objekt gelten"); ObjectSynchronizer :: Benachrichtigung (obj, prüfen); Jvm_endDas ObjectMonitor -Objekt enthält ein _waitset -Warteschlangenobjekt, das alle Threads im Wartezustand enthält und vom ObjectWaiter -Objekt dargestellt wird. Die Benachrichtigung muss tun, um zuerst die Warteschlange des _waitset -Warteschlangens zu erhalten, dann das erste Objektwaiter -Objekt in der Warteschlange zu entfernen und das Objekt dann nach verschiedenen Strategien zu verarbeiten, z. Lösen Sie dann die Warteschlange des _waitset -Warteschlangens. Das entsprechende synchronisierte Sperre löst nicht frei, sodass das Schloss nur freigesetzt werden kann, bis der synchronisierte Synchronisationsblock vorbei ist.
void ObjectMonitor :: musify (fallen) {check_owner (); if (_waitset == null) {tevent (leer -nicht -teure); return;} DTRACE_MONITOR_PROBE (benachrichtigen, this, Object (), Thread); iterator = dequeuewaiter (); if (iterator! ObjectWaiter :: ts_enter;} Iterator-> _ benachrichtigt = 1; ObjectWaiter * list = _EnterryList; if (list! ;} if (policy == 0) {// Vorbereiten Sie die EintragsListif (list == null) {iterator-> _ next = iterator-> _ prev = iterator;} else {list-> _ prev = iterator; iterator-> _ next = list; iterator-> _ prev = null; _ _Entrylist = iTerator; to tueintragListif (list == null) {iterator-> _ next = iterator-> _ prev = null; _EnterryList = iterator;} else {// überlegen: Das Finden des Schwanzes erfordert derzeit einen linearen Lauf von // in der Eintragsliste. Wir können den Schwanzzugriff konstante Zeit erwerben, indem wir in // eine cdll konvertieren, anstatt unseren aktuellen dll.objectwaiter * tail; für (tail = list; tail-> _ Weiter! = Null; schwanz-> _ Weiter); NULL;}} else if (policy == 2) {// Vorbereiten Sie CXQ // vor cxqif (list == null) {iterator-> _ next = iterator-> _ prev = null; _ventrylist = iterator;} else {iterator-> tstate = ObjecthWaiter :: ts_cxq; for (; {tstate = Object ". _cxq; Iterator-> _ Weiter = vorne; if (atomic :: cmpxchg_ptr (iterator, & _cxq, vorne) == vorne) {break;}}}}} else if (policy == 3) {// an anhängen cxqiterator- _cxq; if (tail == null) {iterator-> _ next = null; if (atomic :: cmpxchg_ptr (iterator, & _cxq, null) == null) {break;}} else {while {tail-_ Nächstes. ; Iterator-> _ next = null; break;}}} else {parkevvent * ev = iterator-> _ Ereignis; Iterator-> tState = ObjectWaiter :: TS_RUN; orderAccess :: fence (); ev-> unpark ();} if (Politik <4) {Iterator-> Waitrocks-Waitset-Aterator-Aterator->-Waitet-_-Aterator->-Wait-_-> -Waiter->-Waiteter_reenter_iNer_Beger (} {{iterator-teer-> Die Wartewarteschlange, nicht die Eintragsliste. Wir könnten den Vorgang von Add-to-entrylist oben außerhalb des kritischen Abschnitts verschieben // von _waitSetlock geschützt. In der Praxis ist das nicht nützlich. Mit der Ausnahme von Wait () Timeouts und unterbricht den Monitorbesitzer // der einzige Thread, der _waitsetlock greift. Es gibt fast keinen Inhalt // auf _waitsetLock, daher ist es nicht profitabel, die Länge des // kritischen Abschnitts zu reduzieren.} Thread :: spinRelease (& _WaitsetLock); if (iterator!Benachrichtigung der Methode
Ähnlich wie bei der Benachrichtigungsmethode ist es nur so, dass beim Abrufen der Warteschlange nicht die erste, sondern alle ist.
Wartenmethode
Durch die Wartezeit wird der Thread warten. Die entsprechende lokale Methode ist JVM_MonitorWait, das indirekt ObjectSynchronizer :: Wait nennt, was der Benachrichtigung entspricht. Es ist auch die Wartenmethode, die dem Aufrufen des Objektmonitor -Objekts entspricht. Diese Methode ist lang und wird hier nicht veröffentlicht. Es wird wahrscheinlich ein ObjektWaiter -Objekt erstellt, dann die Warteschlange des _waitset -Warteschlangens abgerufen und das ObjectWaiter -Objekt in die Warteschlange hinzufügen und dann die Warteschlange loslassen. Darüber hinaus wird die entsprechende synchronisierte Sperrung freigesetzt, sodass das Schloss nicht wartet, bis der synchronisierte Synchronisationsblock vorbei ist.
JVM_ENTRY (void, jvm_monitorwait (Jnienv* env, Job -Handle, Jlong MS)) JVMWrapper ("JVM_MonitorWait"); Handle OBJ (Thread, jniHandles :: Resolve_Non_null (Handle)); Assert (obj-> is_instance () || obj-> is_array (), "JVM_MonitorWait muss für ein Objekt angewendet werden"); JavatheadinObjectWaitState Jtiows (Thread, MS! = 0); if (jvmtiexport :: sollte_post_monitor_wait ()) {jvmtiexport :: post_monitor_wait ((javathread *) Thread, (oop) obj (), ms); } ObjectSynchronizer :: Wait (OBJ, MS, Check); jvm_endMethode abschließen
Diese Methode wird verwendet, um aufgerufen zu werden, wenn das Objekt recycelt wird. Dies wird vom JVM unterstützt. Die Abschlussmethode des Objekts tut standardmäßig nichts. Wenn die Unterklasse eine logische Verarbeitung durchführen muss, wenn das Objekt recycelt wird, kann die Abschlussmethode überschrieben werden.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels über Javas Beispielanalyse des Objekts aus der Perspektive des JDK -Quellcode. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!