Objeto é a classe pai de todas as classes, ou seja, todas as classes em Java são herdadas direta ou indiretamente da classe de objeto. Por exemplo, se você criar uma classe, embora não seja declarado explicitamente, é o padrão do ExtendsObject.
Os três pontos a seguir "..." indicam que vários número incerto de parâmetros podem ser aceitos. A maneira antiga de escrever é objeto [], mas é recomendável usar ... na nova versão do Java. Por exemplo
publicvoidgetSomething(String...strings)(){}
Objeto é a classe pai de todas as classes em Java. Ou seja, todas as classes, sejam elas criadas por elas mesmas ou pelas classes do sistema, são herdadas da classe de objeto, ou seja, todas as classes podem substituir a classe de objeto em qualquer ocasião. De acordo com o princípio da substituição de Rich, as subclasses podem substituir sua classe pai em qualquer ocasião, mas a classe pai pode não substituir necessariamente sua subclasse. O que é frequentemente dito em Java é realmente essa verdade! A classe de objeto incorpora as quatro principais características do polimorfismo, herança, encapsulamento e abstração na idéia do OOP!
A classe de objeto é a classe base de todas as classes, não um tipo de dados. Você pode consultar o documento JDK para entender isso, todas as classes são herdadas do objeto.
Objeto ... Objetos Esta definição de parâmetro é uma manifestação polimórfica no caso de parâmetros de método incertos. Ou seja, esse método pode passar vários parâmetros e o número desses parâmetros é incerto. Dessa forma, você precisa fazer algum processamento correspondente no corpo do método. Como o objeto é uma classe base, use o formulário de parâmetro, como objeto ... objetos, permitindo que todos os objetos herdados do objeto como parâmetros. Este método deve ser usado relativamente raramente na prática.
A forma de objeto [] obj é uma forma de parâmetro composta por uma matriz de objeto. Isso significa que os parâmetros desse método são fixos e são uma matriz de objetos. Quanto aos elementos armazenados nesta matriz, eles podem ser objetos herdados de todas as classes de objeto.
É recomendável que você leia essas coisas básicas mais algumas vezes "Thinkinjava"
O objeto de Java é a classe pai de todas as outras classes. Do ponto de vista da herança, é a raiz de nível superior, por isso é também a única classe sem uma classe pai. Ele contém alguns métodos comumente usados para objetos, como getclass, hashcode, igual, clone, tostragem, notificação, espera e outros métodos comumente usados. Portanto, após outras classes que herdam o objeto, eles podem implementar esses métodos sem implementação repetida. A maioria desses métodos são métodos nativos e a seguinte análise detalhada é feita.
O código principal é o seguinte:
classe pública objeto {private estático nativo void Registernatives (); static {Registernatives ();} public Final Native Class <?> getClass (); public native int hashcode (); public boolean equals (objeto obj) {return (this == obj);} clone de objeto nativo () thrrows {Returport (this == obj);} clone de objeto nativo () () Returntsupport; getClass (). getName () + "@" + inteiro.tohexstring (hashcode ());} public final nativo void notify (); public final nativo void notifyAll (); public Final Native Wait (Long Timeout) lança interruptedException; Public Final Wait (Long Timeout, Int Nanos) IlegalargumentException ("O valor do tempo limite é negativo");} if (nanos <0 || nanos> 999999) {lança novo ilegalargumentException ("nanos segundo valor do tempo fora do intervalo"); void finalize () lança articável {}}Método de Registro
Como o método Registernativo é modificado por um bloco estático, o método será executado quando a classe de objeto for carregada. O método local correspondente é java_java_lang_object_registernatives, como segue,
Jniexport void jnicalljava_java_lang_object_registernatives (jnienv *Env, jclass cls) {( *Env)-> Registrativos (Env, cls, métodos, tamanho de (métodos)/sizeof (métodos [0]);}Você pode ver que ele chama indiretamente o método da estrutura JNinativeInterface_, que pode ser simplesmente considerada assim: o que ele faz provavelmente corresponde ao nome do método da camada Java com a função local, para que o mecanismo de execução possa chamar as funções C/C ++ com base nessas tabelas de relacionamento correspondentes ao executar. Como mostrado abaixo, registre esses métodos. Quando o mecanismo de execução executa o método HashCode, ele pode encontrar a função JVM_IHASHCODE da JVM através da tabela de relacionamento. () Também posso saber que os tipos na camada Java devem ser convertidos para o tipo int. Esse mapeamento pode realmente ser considerado como mapeando uma string para um ponteiro de função.
estático jninativethod métodos [] = {{"hashcode", "() i", (void *) e jvm_ihashcode}, {"wait", "(j) v", (void *) e jvm_monitorwait}, {"notify", "() v", (Void *) e {"notifyall", "() v", (void *) e jvm_monitorNotifyAll}, {"clone", "() ljava/lang/object;", (void *) e jvm_clone},}; método getclass
O método getClass também é um método local, e o método local correspondente é java_java_lang_object_getclass, como segue:
Jniexport jclass jnicalljava_java_lang_object_getclass (jnienv *Env, Jobject This) {if (this == null) {jnu_thrownullPointerException (Env, null); retornar 0; } else {return (*Env)-> getObjectClass (Env, isso); }}Então, aqui olhamos principalmente para a função GetObjectClass. A classe correspondente na camada Java na camada C ++ é Klassoop, portanto, os metadados e as informações do método sobre a classe podem ser obtidos através dela.
Jni_entry (jclass, jni_getObjectClass (jnienv *Env, Job 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 :: elenco (k)-> java_mirror ()); Dtrace_probe1 (hotspot_jni, getObjectClass__return, ret); retornar ret; jni_endMétodo HashCode
A partir do método Registernativo anterior, registra vários métodos locais, podemos ver que a função correspondente ao método HashCode é JVM_IHASHCODE, ou seja,
Jvm_entry (jint, jvm_ihashcode (jnienv* Env, identificador de trabalho)) jvmwrapper ("jvm_ihashcode"); // conforme implementado na máquina virtual clássica; Retornar 0 se o objeto for alça de retorno nulo == NULL? 0: ObjectSynchronizer :: FasthashCode (Thread, jniHandles :: resolve_non_null (handle)); jvm_endA lógica gerada para HashCode é determinada pela função get_next_hash do synchronizer.cpp. A implementação é relativamente complexa. Existem diferentes estratégias de geração com base em diferentes valores do HashCode e, finalmente, uma máscara de hash é usada para processá -la.
estático em linha intptr_t get_next_hash (thread * self, oop obj) {intptr_t value = 0; if (hashcode == 0) {value = os :: aleather ();} else (hashcode == 1) {intptr_t addrbits = intptr_t (jj)>>> Gvars.stwrandom;} else if (hashcode == 2) {value = 1; // para teste de sensibilidade} else if (hashcode == 3) {value = ++ gvars.hcSequence;} else if (hashcode == 4) {value = intpsts); << 11); auto-> _ hashstatex = self-> _ hashstatey; self-> _ hashstatey = self-> _ hashstatez; self-> _ hashstatez = self-> _ hashstatew; não assinou v = self-> _ hashstatew; ; Método igual
Este é um método não local, e a lógica do julgamento é muito simples e é diretamente == comparação.
Método do clone
Na tabela de métodos local, sabemos que a função local correspondente ao método clone é JVM_CLONE. O método clone implementa principalmente a função de clonagem do objeto e gera o mesmo novo objeto com base no objeto (os atributos do objeto de nossa classe comum clonarão o valor se for um tipo primitivo, mas se for um objeto, o endereço do objeto será clonado). Para implementar a clonagem das classes Java, você precisa implementar a interface clonável. Se (! Klass-> is_cloneable ()) verificar se a interface é implementada. Em seguida, determine se o espaço de memória é alocado em duas situações. O novo objeto é new_obj e, em seguida, copiar e a estrutura de dados da camada C ++ está definida para new_obj. Finalmente, ele será convertido para o tipo de trabalho para o tipo de objeto Java Camyer.
Jvm_entry (Jobject, JVM_CLONE (JNIENV* ENV, HANDEJA DE TRABALHO)) JVMWRAPER ("JVM_CLONE"); HOLLE OBJ (Thread, JniHandles :: Resolve_non_null (Handle)); const KlassHle Klass (Thread, Obj-> Klasl (); (! klass-> is_clOnEable ()) {ResourceMark rm (thread); throw_msg_0 (vmsymbols :: java_lang_clonenotsupportException (), klass-> extern_name ());} const size = obj-> tamanho (); oOp_Obj * comprimento = ((Arrayop) obj ())-> length (); new_obj = coletadoHeap :: Array_allocate (klass, tamanho, comprimento, check_null);} else {new_obj = colectedheap :: obj_allocate (klass, size, check_null); (} cópia ::JONT_JONTS_LONGS_Alnong (Klass, size_null); (} cópia ::JONT_JLONG. (JLONG*) new_obj, (size_t) align_object_size (size) / heapwordsperlong); new_obj-> init_mark (); barrierset* bs = universo :: heap ()-> barrier_set (); assert (bs- has has Hande_write_region_opt (), write_region "); bs-> write_region (memregion ((heapword*) new_obj, size)); if (klass-> has_finizer ()) {assert (obj-> is_instance ()," deve ser instanhooop "); newoBJ = instancen): :: Register_finalizer () (); JniHandles :: make_local (Env, OOP (new_obj)); jvm_endMétodo da ToString
A lógica é obter o nome da classe Plus @ Plus HexadeCimal HashCode.
notificar o método
Este método é usado para acordar o encadeamento e as instruções finais de modificação não podem ser reescritas. O método local correspondente é JVM_MONITORNOTIFY. ObjectSynchronizer :: Notify acabará chamando de ObjectMonitor :: notify (armps). Esse processo é que o ObjectSynchronizer tentará obter o objeto FreeObjectMonitor no thread atual e tentará obtê -lo do global se ele falhar.
Jvm_entry (void, jvm_monitorNotify (jnienv* Env, Job Handle)) jvmwrapper ("jvm_monitorNotify"); Lidar com OBJ (Thread, jniHandles :: Resolve_Non_Null (Handle)); assert (obj-> is_instance () || obj-> is_array (), "jvm_monitorNotify deve se aplicar a um objeto"); ObjectSynchronizer :: notify (obj, check); Jvm_endO objeto ObjectMonitor contém um objeto de fila de _waitset, que contém todos os threads no estado de espera e é representado pelo objeto Objectwaiter. O que o Notify precisa fazer é primeiro obter o bloqueio da fila _waitset e remover o primeiro objeto Objectwaiter na fila _waitset e depois processar o objeto de acordo com diferentes estratégias, como adicioná -lo à fila _entrylist. Em seguida, solte o bloqueio da fila _waitset. Ele não libera o bloqueio correspondente do sincronizado; portanto, o bloqueio só pode ser liberado até que o bloco de sincronização sincronizado termine.
Void ObjectMonitor :: notify (armps) {check_owner (); if (_waitSet == null) {tevent (notify vazio); return;} dtrace_monitor_probe (notificar, isto, object (), thread); int thread = knoB_movenTifyee; thread:: spinacire (), _); iterator = dequeuewaiter (); if (iterator! = null) {tevent (notify1-transfer); garantia (iterador-> tstate == objectwaiter :: ts_wait, "invariant"); Objectwaiter :: ts_enter;} iterator-> _ notificou = 1; objectwaiter * list = _entryList; if (list! = Null) {assert (list-> _ prev == null, "invariante"); } if (Policy == 0) {// Prenda a Entrylistif (list == null) {iterator-> _ a próxima = iterator-> _ prev = iterator;} else {list-> _ prev = nuln; Anexe ao Entrylistif (list == null) {iterator-> _ a próxima = iterator-> _ prev = null; _entryList = iterator;} else {// Considere: Encontrar a cauda requer atualmente uma caminhada em tempo linear da // a lista de entrada. Podemos fazer acesso à cauda em tempo constante convertendo em // uma CDLL em vez de usar nossa dll.objectwaiter * cauda; para (cauda = list; cauda-> _ a próxima! = Null; cauda = cauda-> _ a seguir); assert (cauda! = Null;}} else if (policy == 2) {// prenda a cxq // prenda a cxqif (list == null) {iterator-> _ a próxima = iterator-> _ prev = null; _entryList = itator;} else {itator-> tstate = objecter; _cxq; iterator-> _ next = front; if (atomic :: cmpxchg_ptr (iterator, & _cxq, front) == front) {break;}}}}}} else (policy == 3) {// anexar a cxqiterator-> tSTATE = objetos: _cxq; if (cauda == null) {iterator-> _ next = null; if (atomic :: cmpxchg_ptr (iterator, & _cxq, null) == null) {break;}}; ; iterator-> _ a próxima = null; break;}}} else {parkevent * ev = iterator-> _ evento; iterator-> tstate = objectwaiter :: ts_run; orderaccess :: fence (); ev-> underk ();} if (policy <4) {iteRer-> Protege a fila de espera, não a lista de entrada. Poderíamos // mover a operação Add-to-Intrylist, acima, fora da seção crítica // protegido por _waitsetLock. Na prática, isso não é útil. Com a // exceção dos tempos de espera () e interrompe o proprietário do monitor // é o único thread que agarra _waitsetLock. Quase não há conteúdo // em _waitsetLock, portanto, não é lucrativo reduzir a duração da seção // crítica.} Thread :: spinRelease (& _waitsetLock); if (iterator! = Null && _ _ _ _nynt: _ sync_notificações!notifyAll método
Semelhante ao método Notify, é apenas que, ao buscar a fila _waitset, não é a primeira, mas tudo.
Método de espera
O método de espera faz o thread esperar. Seu método local correspondente é JVM_monitorwait, que indiretamente chama de objectSynchronizer :: wait, que corresponde ao notificar. É também o método de espera correspondente a chamar o objeto ObjectMonitor. Este método é longo e não será publicado aqui. Provavelmente, é para criar um objeto Objectwaiter, obter o bloqueio da fila _waitset e adicionar o objeto Objectwaiter à fila e, em seguida, solte o bloqueio da fila. Além disso, ele liberará o bloqueio correspondente do sincronizado, para que a trava não espere até que o bloco de sincronização sincronizado termine.
Jvm_entry (void, jvm_monitorwait (jnienv* Env, Job Handle, jlong ms)) jvmwrapper ("jvm_monitorwait"); Lidar com OBJ (Thread, jniHandles :: Resolve_Non_Null (Handle)); assert (obj-> is_instance () || obj-> is_array (), "jvm_monitorwait deve se aplicar a um objeto"); Javathreadinobjectwaitstate jtiows (thread, ms! = 0); if (jvmtiexport :: deve_post_monitor_wait ()) {jvmtiexport :: post_monitor_wait ((javathread *) thread, (oop) obj (), ms); } ObjectSynchronizer :: wait (obj, ms, check); jvm_endFinalize o método
Este método é usado para ser chamado quando o objeto é reciclado. Isso é suportado pela JVM. O método Finalize of Object não faz nada por padrão. Se a subclasse precisar executar algum processamento lógico quando o objeto for reciclado, o método Finalize poderá ser substituído.
Resumir
O exposto acima é todo o conteúdo deste artigo sobre a análise de exemplo de Java do objeto da perspectiva do código -fonte do JDK. Espero que seja útil para todos. Amigos interessados podem continuar se referindo a outros tópicos relacionados neste site. Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!