El objeto es la clase principal de todas las clases, es decir, todas las clases en Java se heredan directa o indirectamente de la clase de objeto. Por ejemplo, si crea una clase, aunque no se establece explícitamente, es el valor predeterminado de ExtendSObject.
Los siguientes tres puntos "..." indican que se pueden aceptar varios números inciertos de parámetros. La antigua forma de escribir es ObjectArgs [], pero se recomienda usar ... en la nueva versión de Java. Por ejemplo
publicvoidgetSomething(String...strings)(){}
El objeto es la clase principal de todas las clases en Java. Es decir, todas las clases, ya sean creadas por ellos mismos o las clases en el sistema, se heredan de la clase de objetos, es decir, todas las clases pueden reemplazar la clase de objetos en cualquier ocasión. Según el principio del reemplazo de Rich, las subclases pueden reemplazar su clase principal en cualquier ocasión, pero la clase principal no necesariamente reemplaza su subclase. ¡Lo que a menudo se dice en Java es en realidad esta verdad! ¡La clase de objeto encarna las cuatro características principales del polimorfismo, la herencia, la encapsulación y la abstracción en la idea OOP!
La clase de objeto es la clase base de todas las clases, no un tipo de datos. Puede consultar el documento JDK para comprender esto, todas las clases se heredan de Object.
Objeto ... Objetos Esta definición de parámetros es una manifestación polimórfica en el caso de los parámetros del método incierto. Es decir, este método puede pasar múltiples parámetros, y el número de estos parámetros es incierto. De esta manera, debe realizar un procesamiento correspondiente en el cuerpo del método. Debido a que el objeto es una clase base, use la forma de parámetros como los objetos ... objetos, permitiendo todos los objetos heredados del objeto como parámetros. Este método debe usarse relativamente raramente en la práctica.
La forma de objeto [] obj es una forma de parámetro compuesta por una matriz de objetos. Esto significa que los parámetros de este método son fijos y son una matriz de objetos. En cuanto a los elementos almacenados en esta matriz, pueden ser objetos heredados de todas las clases de objeto.
Se recomienda que lea estas cosas básicas varias veces más "ThinkInjava"
El objeto de Java es la clase principal de todas las demás clases. Desde la perspectiva de la herencia, es la raíz de nivel superior, por lo que también es la única clase sin una clase principal. Contiene algunos métodos de uso común para objetos, como GetClass, Hashcode, Equals, Clon, ToString, Notify, Wait y otros métodos de uso común. Por lo tanto, después de que otras clases hereden el objeto, pueden implementar estos métodos sin implementación repetida. La mayoría de estos métodos son métodos nativos, y se realiza el siguiente análisis detallado.
El código principal es el siguiente:
objeto de clase pública {private static nation void registernates (); static {registernates ();} public final class nativo <?> getClass (); public nation int hashcode (); public boolean iguales (obj Obj) {return (this == obj);} clone de objeto nativo protegido () shows clonenSupportedException; public string tostring () getClass (). GetName () + "@" + Integer.ToHexString (hashCode ());} public Final Native Natify Notify (); public Final Final Native Notifyall (); public Final Native Void Wait (Long Timeout) lanza InterruptedException; Public Final Void Wait (Long TimeOut, int nanos) lanzada InterruptedException {si (Tiempo Tiempo Tiempo Tiempo Tiempo de tiempo (0) público. IlegalArGumentException ("El valor del tiempo de espera es negativo");} if (nanos <0 || nanos> 9999999) {throw newleLarGumentException ("Nanos Segundo valor de tiempo de espera de rango");} if (nanos> 0) {tiempo de espera ++;} espera (tiempo de tiempo);} Public Final Wait (). Void Finalize () lanza lanzable {}}Método Registro de Registro
Dado que el método de registro de registro se modifica mediante un bloque estático, el método se ejecutará cuando se cargue la clase de objeto. El método local correspondiente es java_java_lang_object_registernatives, como sigue,
Jniexport void jnicalljava_java_lang_object_registernatives (jnienv *env, jclass cls) {( *env)-> registrarnates (env, cls, métodos, sizeof (métodos)/sizeof (métodos [0]));}Puede ver que llama indirectamente el método de la estructura JninativeInterface_, que simplemente puede considerarse como esto: lo que hace probablemente corresponda al nombre del método de la capa Java con la función local, para que el motor de ejecución pueda llamar a las funciones C/C ++ basadas en estas tablas de relación correspondientes al ejecutar el código de bytecode. Como se muestra a continuación, registre estos métodos. Cuando el motor de ejecución ejecuta el método hashcode, puede encontrar la función jvm_ihashcode de JVM a través de la tabla de relaciones. () También puedo saber que los tipos de la capa Java deben convertirse en Tipo int. Esta asignación puede considerarse como asignar una cadena a un puntero de funciones.
Métodos static jninativemethod [] = {{"hashcode", "() i", (void *) & jvm_ihashcode}, {"espera", "(j) v", (void *) & jvm_monitorwait}, {"notificar", "() v", (void *) y jvm_monitroToTify}, {notify "() V", (void *) & jvm_monitornotifyall}, {"clone", "() ljava/lang/object;", (void *) & jvm_clone},}; Método GetClass
El método GetClass también es un método local, y el método local correspondiente es java_java_lang_object_getclass, como sigue:
Jniexport Jclass jnicalljava_java_lang_object_getclass (jnienv *env, jobject this) {if (this == null) {jnu_thrownullpointerexception (env, null); regresar 0; } else {return (*env)-> getObjectClass (env, this); }}Así que aquí miramos principalmente la función GetObjectClass. La clase correspondiente en la capa Java en la capa C ++ es Klassoop, por lo que los metadatos y la información del método sobre la clase se pueden obtener a través de ella.
Jni_entry (jclass, jni_getObjectClass (jnienv *env, trabajo 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_endmétodo hashcode
Del método de registro anterior registra varios métodos locales, podemos ver que la función correspondiente al método hashcode es jvm_ihashcode, es decir, es,
Jvm_entry (jint, jvm_ihashcode (jnienv* env, job manejo)) jvmwrapper ("jvm_ihashcode"); // tal como se implementa en la máquina virtual clásica; return 0 si el objeto es nulo return many == null? 0: ObjectSynChronizer :: FastHashCode (Thread, JniHandles :: Resolve_Non_Null (Handle)); JVM_ENDLa lógica generada para hashcode está determinada por la función get_next_hash de synchronizer.cpp. La implementación es relativamente compleja. Existen diferentes estrategias de generación basadas en diferentes valores de hashcode, y finalmente se utiliza una máscara hash para procesarlo.
estática en línea intptr_t get_next_hash (Thread * self, oop obj) {intptr_t value = 0; if (hashcode == 0) {value = OS :: OS :: Random ();} más Gvars.stwrandom;} else if (hashcode == 2) {value = 1; // para pruebas de sensibilidad} else if (hashcode == 3) {value = ++ gvars.hcSequence;} else if (hashcode == 4) {value = intptr_t (obj);} else {sin señalización t = self-> _ Hashshtat 11); self-> _ hashstatex = self-> _ hashstatey; self-> _ hashstatey = self-> _ hashstatez; self-> _ hashstatez = self-> _ hashstatew; unsigned v = self-> _ hashstatew; v = (v ^ (v >> 19)) ^ (t >> 8) ; Self-> _ hashstatew = v; value = v;} value & = kickoopdesc :: hash_mask; if (valor == 0) valor = 0xbad; afirmar (valor! = Markopdesc :: no_hash, "invariant"); tevent (hashcode: generate); valor de retorno;} Método igual
Este es un método no local, y la lógica del juicio es muy simple, y es directamente == comparación.
método clon
Desde la tabla de métodos locales, sabemos que la función local correspondiente al método clon es jvm_clone. El método de clon implementa principalmente la función de clonación del objeto y genera el mismo objeto nuevo basado en el objeto (los atributos del objeto de nuestra clase común clonarán el valor si es un tipo primitivo, pero si es un objeto, la dirección del objeto se clonará). Para implementar la clonación de las clases de Java, debe implementar la interfaz clonable. If (! Klass-> is_clonable ()) verificará si se implementa la interfaz. Luego determine si el espacio de memoria se asigna en dos situaciones. El nuevo objeto es new_obj, y luego copiar y la estructura de datos de la capa C ++ se establecen para new_obj. Finalmente, se convertirá en el tipo de trabajo al tipo de objeto Java Layer.
Jvm_entry (Jobject, JVM_Clone (Jnienv* Env, Job Handle)) JVMWrapper ("JVM_CLONE"); Handle Obj (Thread, JniHandles :: Resolve_Non_Null (Handle); (! klass-> is_clonable ()) {resourcemark rm (hilo); throw_msg_0 (vmsymbols :: java_lang_clonenotsupportedException (), klass-> external_name ());} const size = obj-> size (); oop new_obj = null; if (obj-> is_jaS longitud = ((Arrayoop) obj ())-> longitud (); new_obj = recopLedHeap :: array_allocate (klass, size, longitud, check_null);} else {new_obj = recopiledheap :: obj_allocate (klass, size, check_null);} copy :: conjunto_jlongs_atomic ((jlong*) objer (jlong*) new_obj, (size_t) align_object_size (size) / HeapwordSperlong); new_obj-> init_mark (); barrierset* bs = universe :: heap ()-> barrier_set (); asignar (bs-> has_write_region_opt () ". write_region "); bs-> write_region (memregion ((Heapword*) new_obj, size)); if (klass-> has_finalizer ()) {ASERT (obj-> is_instance ()," debería ser instanciapía "); new_obj = instanciaklass :: register_finalizer (instinhoop Jnihandles :: make_local (env, oop (new_obj)); jvm_endmétodo de tostración
La lógica es obtener el nombre de clase más @ plus hexadecimal hashcode.
Notificar método
Este método se utiliza para despertar el hilo, y las instrucciones finales de modificación no se pueden reescribir. El método local correspondiente es JVM_Monitornotify. ObjectSynChronizer :: Notify eventualmente llamará a ObjectMonitor :: notificar (trampas). Este proceso es que ObjectSynCronizer intentará obtener el objeto FreeObjectMonitor en el hilo actual e intentar obtenerlo de lo global si falla.
Jvm_entry (void, jvm_monitornotify (jnienv* env, Job Handle)) JVMWrapper ("JVM_Monitornotify"); Manejar obj (hilo, jnihandles :: resolve_non_null (mango)); afirmar (obj-> is_instance () || obj-> is_array (), "jvm_monitornotify debe aplicarse a un objeto"); ObjectSynChronizer :: notify (obj, verificar); JVM_ENDEl objeto ObjectMonitor contiene un objeto de cola _WaitSet, que contiene todos los hilos en el estado de espera y está representado por el objeto ObjectSwairter. Lo que debe hacer que debe hacer es obtener primero el bloqueo de cola _WaitSet, luego eliminar el primer objeto ObjectSwaitar en la cola _WaitSet y luego procesar el objeto de acuerdo con diferentes estrategias, como agregarlo a la cola _Entrylist. Luego suelte el bloqueo de cola _WaitSet. No libera el bloqueo correspondiente de sincronizado, por lo que el bloqueo solo se puede lanzar hasta que termine el bloque de sincronización sincronizado.
void ObjectMonitor :: notify (Traps) {check_owner (); if (_WaitSet == null) {TeVent (vacía -notify); return;} dtrace_monitor_probe (notify, this, object (), thread); int policy = knob_movenotifyee; hilo :: spinacquire (& _waitsetlock, "waitset - notify"); Dequeuewaiter (); if (iterator! = Null) {teVent (notify1-transfer); garantía (iterator-> tstate == objectWaiter :: ts_wait, "invariant"); garantía (iterator-> _ notificado == 0, "invariante"); if (política! = 4) {iterator-> tstate = objectwaTer :: ;} iterator-> _ notificado = 1; ObjectWaiter * list = _EntryList; if (list! = Null) {ASSERT (LIST-> _ PREV == NULL, "Invariant"); Afirmación (LIST-> TSTATE == ObjectWaIter :: TS_enter, "Invariant"); ASSER {// Prepender a EntryListif (list == null) {iterator-> _ next = iterator-> _ prev = iterator;} else {list-> _ prev = iterator; iterator-> _ next = list; iterator-> _ = null; _Entrylist = iterator;}} if (Policy ==) == null) {iterator-> _ next = iterator-> _ prev = null; _entryList = iterator;} else {// Considere: encontrar la cola actualmente requiere una caminata de tiempo lineal de // la lista de entrada. Podemos hacer que el acceso a la cola constante se convierta en // un CDLL en lugar de usar nuestro dll.ObjectWaiter actual actual; para (Tail = List; Tail-> _ Next! = Null; Tail = Tail-> _ Next); Afirmar (Tail! = Null && Tail-> _ Next == Null, "Invariante"); Tail-> _ Next = Iterator; Iterator-itherator-itherator-_siderator-_ Tail _ Next ==, "Invariante"); Tail-> _ Next = Iterator; Iterator-> _ Tail _ Tail = Tail = Tail = Tail = Tail = Tail = Tail = Tail = Tail = Tail = Tail = Tail ; iterator-> _ next = null;}} else if (Policy == 2) {// Prepender a cxq // Prepend to cxqif (list == null) {iterator-> _ next = iterator-> _ prev = null; _Entrylist = iterator;} else {iterator-> tstate = ObjectWaiter :: ts_; {ObjectWaIter * front = _cxq; iterator-> _ next = front; if (atomic :: cmpxchg_ptr (iterator, & _cxq, front) == front) {break;}}}} else if (Policy == 3) {// Append to cxqiterator-> tstate = ObjectWaiter :: ts_cs_cs_; {ObjectWaIter * tail; tail = _cxq; if (tail == null) {iterator-> _ next = null; if (atomic :: cmpxchg_ptr (iterator, & _cxq, null) == null) {break;}} else {while (tail-> _! = Null) ; iterator-> _ prev = Tail; iterator-> _ next = null; break;}}} else {parkevent * ev = iterator-> _ event; iterator-> tstate = objectWaIter :: ts_run; ordenaccess :: frence (); ev-> impark ();} if (política <4) {iterator-> wait_reenter_begin (this);} // _WaitSetLock protege la cola de espera, no la lista de entrada. Podríamos // mover la operación Agregar a In-EntryList, arriba, fuera de la sección crítica // protegida por _WaitSetLock. En la práctica eso no es útil. Con la excepción // de espera () tiempos de espera e interrumpe el propietario del monitor // es el único hilo que toma _WaitSetLock. Casi no hay contenido // en _WaitSetLock, por lo que no es rentable reducir la longitud de la sección // crítica.} Thread :: spinRelease (& _WaitSetLock); if (iterator! = NULL && ObjectMonitor :: _ Sync_notifications! = NULL) {ObjectMonitor :: _ Sync_notifications-> Inc (); _ Sync_notificationsMétodo de notificación
Similar al método de notificación, es solo que al obtener la cola _WaitSet, no es la primera sino todo.
Método de espera
El método de espera hace que el hilo espere. Su método local correspondiente es jvm_monitorwait, que indirectamente llama ObjectSynCronizer :: Wait, que corresponde a notificar. También es el método de espera correspondiente a llamar al objeto ObjectMonitor. Este método es largo y no se publicará aquí. Probablemente sea para crear un objeto ObjectWaiter, luego obtener el bloqueo de cola _WaitSet y agregar el objeto ObjectWaIter a la cola, y luego suelte el bloqueo de la cola. Además, liberará el bloqueo correspondiente de sincronizado, por lo que el bloqueo no espera hasta que termine el bloque de sincronización sincronizado.
Jvm_entry (void, jvm_monitorwait (jnienv* Env, Job Handle, JLong MS)) JVMWrapper ("JVM_Monitorwait"); Manejar obj (hilo, jnihandles :: resolve_non_null (mango)); afirmar (obj-> is_instance () || obj-> is_array (), "jvm_monitorwait debe aplicarse a un objeto"); JavathreadinObjectWaitState Jtiows (hilo, ms! = 0); if (jvmtiexport :: debería_post_monitor_wait ()) {jvmtiexport :: post_monitor_wait ((javathread *) hilo, (oop) obj (), ms); } ObjectSynChronizer :: Wait (obj, ms, check); jvm_endMétodo finalizar
Este método se utiliza para llamarse cuando el objeto se recicla. Esto es compatible con el JVM. El método de finalización del objeto no hace nada por defecto. Si la subclase necesita realizar algún procesamiento lógico cuando el objeto se recicla, el método finalizar puede anularse.
Resumir
Lo anterior es todo el contenido de este artículo sobre el análisis de ejemplo de Java del objeto desde la perspectiva del código fuente JDK. Espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!