Объект - это родительский класс всех классов, то есть все классы в Java унаследованы прямо или косвенно от класса объекта. Например, если вы создаете класс, хотя это не указано явно, это дефолт ExtendsObject.
Следующие три пункта «...» указывают на то, что может быть принято несколько неопределенных параметров. Старый способ написания - это объект, но он рекомендуется использовать ... в новой версии Java. Например
publicvoidgetSomething(String...strings)(){}
Объект - это родительский класс всех классов в Java. То есть все классы, независимо от того, создаются ли они самим собой или классами в системе, унаследованы от класса объектов, то есть все классы могут заменить класс объектов в любом случае. Согласно принципу замены Рича, подклассы могут заменить их родительский класс в любом случае, но родительский класс не обязательно заменить их подкласс. То, что часто говорят на Java, на самом деле это правда! Класс объекта воплощает в себе четыре основные характеристики полиморфизма, наследования, инкапсуляции и абстракции в идее ООП!
Класс объектов - это базовый класс всех классов, а не тип данных. Вы можете запросить документ JDK, чтобы понять это, все классы унаследованы от объекта.
Объект ... Объекты Это определение параметра является полиморфным проявлением в случае неопределенных параметров метода. То есть этот метод может передавать несколько параметров, и число этих параметров является неопределенным. Таким образом, вам нужно сделать некоторую соответствующую обработку в теле метода. Поскольку объект является базовым классом, используйте форму параметров, такую как объект ... объекты, позволяющие всем объектам, унаследованным от объекта в качестве параметров. Этот метод следует использовать относительно редко на практике.
Форма объекта [] obj - это форма параметров, состоящая из массива объектов. Это означает, что параметры этого метода фиксируются и являются массивом объектов. Что касается элементов, хранящихся в этом массиве, они могут быть объектами, унаследованными от всех классов объекта.
Рекомендуется прочитать эти базовые вещи еще несколько раз "Thinkinjava"
Цель Java - родительский класс всех других классов. С точки зрения наследства, это корень верхнего уровня, поэтому он также является единственным классом без родительского класса. Он содержит некоторые часто используемые методы для объектов, таких как GetClass, Hashcode, Equals, Clone, Tostring, уведомление, ожидание и другие часто используемые методы. Следовательно, после других классов, наследственных объекта, они могут реализовать эти методы без повторной реализации. Большинство из этих методов являются собственными методами, и проводится следующий подробный анализ.
Основной код заключается в следующем:
открытый объект класса {частный статический нативный void registernative (); static {registernative ();} public final Class <?> getClass (); public native int hashcode (); public boolean equals (Object obj) {return (this == obj);} защищенный нативный объект () ThroNeNotsU getClass (). getName () + "@" + integer.tohexstring (hashcode ());} public final final void notify (); AllogalargumentException ("Значение тайм -аута отрицательно");} if (nanos <0 || nanos> 999999) {Thress new allosalargumentException ("nanos второе временное значение вне диапазона");} if (nanos> 0) {timeout ++;} waive (timeout);) void infintize () бросает броски {}}Метод регистрации
Поскольку метод регистративных средств модифицируется статическим блоком, метод будет выполнен при загрузке класса объекта. Соответствующий локальный метод - java_java_lang_object_registernative, следующим образом,
Jniexport void jnicalljava_java_lang_object_registernative (jnienv *env, jclass cls) {( *env)-> Registernative (env, cls, методы, sizeof (методы)/sizeof (methods [0]);};};};};};Вы можете видеть, что он косвенно вызывает метод структуры jninativeInterface_, который можно просто рассматривать как это: то, что он делает, вероятно, соответствует имени метода слоя Java с локальной функцией, так что механизм выполнения может вызывать функции C/C ++ на основе этих соответствующих таблиц взаимоотношений при выполнении байт -кода. Как показано ниже, зарегистрируйте эти методы. Когда механизм выполнения выполняет метод хэшкода, он может найти функцию JVM JVM_IHASHCODE через таблицу отношений. () Я также могу знать, что типы на слое Java должны быть преобразованы в тип Int. Это отображение может фактически рассматриваться как отображение строки с указателем функции.
Static jninativemethod Methods [] = {{"hashcode", "() i", (void *) & jvm_ihashcode}, {"wate", "(j) v", (void *) & jvm_monitorwait}, {"notefy", ",", void *) & jvm_monit "() 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, jobjuct this) {if (this == null) {jnu_thrownullPointerException (env, null); возврат 0; } else {return (*env)-> getObjectClass (env, this); }}Итак, здесь мы в основном смотрим на функцию GetObjectClass. Соответствующим классом в слое Java в слое C ++ является Klassoop, поэтому через него можно получить метаданные и метод информации о классе.
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 :: capt (k)-> java_mirror ()); Dtrace_probe1 (hotspot_jni, getobjectclass__return, ret); вернуть ret; jni_endметод хэшкода
Из предыдущего метода регистрации регистрируется несколько локальных методов, мы видим, что функция, соответствующая методу хэшкода, является jvm_ihashcode, то есть
Jvm_entry (jint, jvm_ihashcode (jnienv* env, jass handle)) jvmwrapper ("jvm_ihashcode"); // как реализовано в классической виртуальной машине; возврат 0, если объект является null return handle == null? 0: ObjectSynchronizer :: fasthashcode (Thread, jnihandles :: resolve_non_null (handle)); jvm_endЛогика, сгенерированная для хэшкода, определяется функцией get_next_hash of synchronizer.cpp. Реализация относительно сложна. Существуют различные стратегии генерации, основанные на различных значениях хэшкода, и, наконец, для его обработки используется хэш -маска.
Статический 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; Gvars.stwrandom;} else if (hashcode == 2) {value = 1; // для тестирования чувствительности} else if (hashcode == 3) {value = ++ gvars.hc secestence;} else (hashcode == 4) {value = intptr_t (Obj); << 11); self-> _ hashstatex = self-> _ hashstatey; self-> _ hashstatey = self-> _ hashstatez; self-> _ hashstatez = self-> _ hashstatew; без знака v = self-> _ hashstatew; v = (v >> 19) ; Self-> _ hashstatew = v; value = v;} value & = markoopdesc :: hash_mask; if (value == 0) value = 0xbad; assert (value! = Markoopdesc :: no_hash, "Invariant"); Devent (hashcode: генерировать); ЭКВАЛЬНЫЙ МЕТОД
Это нелокальный метод, и логика суждения очень проста, и это напрямую == сравнение.
Метод клона
Из локальной таблицы методов мы знаем, что локальная функция, соответствующая методу клона, является JVM_CLONE. Метод клона в основном реализует функцию клонирования объекта и генерирует тот же новый объект на основе объекта (атрибуты объекта нашего общего класса будут клонировать значение, если это примитивный тип, но если это объект, то адрес объекта будет клонирован). Чтобы внедрить клонирование классов Java, вам необходимо реализовать клонируемый интерфейс. If (! Klass-> is_clonable ()) проверит, реализован ли интерфейс. Затем определите, выделяется ли пространство памяти в двух ситуациях. Новый объект - new_obj, а затем скопируйте и структуру данных слоя C ++ установлены для new_obj. Наконец, он будет преобразован в тип задания в тип объекта слоя Java.
Jvm_entry (jobject, jvm_clone (jnienv* env, jab handle)) jvmwrapper ("jvm_clone"); обрабатывать obj (поток, jnihandles :: resolve_non_null (handle)); const klasshandle klass (thread, obj-> klass ()); (! klass-> is_clonable ()) {resourcemark rm (поток); throw_msg_0 (vmsymbols :: java_lang_clonenotsupportedexception (), klass-> external_name ());} const int size = obj-> size (); op new_obj = null ((arrayoop) obj ())-> length (); new_obj = collectedHeap :: array_allocate (klass, размер, длина, check_null);} else {new_obj = collectedHeap :: obj_allocate (klass, size, check_null);} copy :: concoint_jlongs_atomic (jlong*obj (), obj (), obj (), obj (obj);} (jlong*) new_obj, (size_t) align_object_size (size) / heapwordsperlong); new_obj-> init_mark (); barrierset* bs = Universe :: heap ()-> barrier_set (); write_region "); bs-> write_region (memregion ((heapword*) new_obj, size)); if (klass-> has_finalizer ()) {assert (obj-> is_instance ()," должен быть exantemploip "); new_obj = exantemplass :: register_finaliz Jnihandles :: make_local (env, oop (new_obj)); jvm_endМетод ToString
Логика состоит в том, чтобы получить имя класса плюс @ плюс шестнадцатеричный хешкод.
Уведомить метод
Этот метод используется для разбуждения потока, и окончательные инструкции по изменению не могут быть переписаны. Соответствующим локальным методом является jvm_monitornotify. ObjectSynchronizer :: notify в конечном итоге вызовет ObjectMonitor :: notify (TRAPS). Этот процесс заключается в том, что ObjectSynchronizer попытается получить объект FreeObjectMonitor в текущем потоке и попытаться получить его из глобального, если он не удастся.
Jvm_entry (void, jvm_monitornotify (jnienv* env, grame)) jvmwrapper ("jvm_monitornotify"); Обработка obj (Thread, jnihandles :: resolve_non_null (handle)); assert (obj-> is_instance () || obj-> is_array (), "jvm_monitornotify должен применяться к объекту"); ObjectSynchronizer :: notify (obj, проверка); Jvm_endОбъект ObjectMonitor содержит объект QuaitSet Queue, который удерживает все потоки в состоянии ожидания и представлен объектом ObjectWaiter. Что нужно сделать, так это сначала получить блокировку очереди _waitSet, затем удалить первый объект ObjectWaiter в очереди _waitSet, а затем обработать объект в соответствии с различными стратегиями, такими как добавление в очередь _EntryList. Затем отпустите блокировку очереди _waitSet. Он не высвобождает соответствующую блокировку синхронизации, поэтому блокировка может быть высвобождена только до тех пор, пока не закончится синхронизированный блок синхронизации.
void objectMonitor :: notify (TRAPS) {check_Owner (); if (_WaitSet == nul Dequeuewaiter (); if (iterator! = Null) {tevent (notify1-transfer); гарантия (итератор-> tstate == ObjectWaiter :: ts_wait, "Invariant"); Гарантию (итератор-> _ уведомлен == 0, "Invariant"); if (политика! ;} iterator-> _ natified = 1; objectwaiter * list = _entrylist; if (list! = null) {assert (list-> _ prev == null, "Invariant"); Assert (list-> tstate == ObjectWaiter :: ts_enter, "Invariant"); {// Prepend to intrplistif (list == null) {iterator-> _ next = iterator-> _ prev = iterator;} else {list-> _ aretrator; iterator-> _ next = list; iterator-> _ null; _Entrylist = iterator;}} else else (if == 1). Null) {iterator-> _ next = iterator-> _ prev = null; _entrylist = iterator;} else {// рассмотреть: поиск хвоста в настоящее время требует ходьбы линейного времени // начального списка. Мы можем сделать постоянное время доступа к хвосту, преобразуя в // cdll вместо использования нашего текущего dll.objectwaiter * hail; for (tail = list; hail-> _ next! = Null; хвост-> _ next); assert (хвост! = Null && hail-> _ next == null, "Invariant"); hail-next = iTerator = Null;}} else if (police == 2) {// prepend к cxq // prepend to cxqif (list == null) {iterator-> _ next = iterator-> _ prev = null; _Entrylist = iterator;} else {iterator-> tstate = objectwaiter :: ts_cx; _cxq; iterator-> _ next = front; if (atomic :: cmpxchg_ptr (итератор, & _cxq, front) == front) {break;}}}} else if (policy == 3) {// Приложение к cxquterator-> tstate = objectwaiter :: ts_cx; _cxq; if (tail == null) {iterator-> _ next = null; if (atomic :: cmpxchg_ptr (iterator, & _cxq, null) == nul ; итератор-> _ next = null; break;}}} else {parkevent * ev = iterator-> _ event; iterator-> tstate = objectwaiter :: ts_run; orderaccess :: farger (); ev-> unpark ();} if (политика <4) {iterator-> wait_reenter_beger (это); Подождите очередь, а не список заявок. Мы могли бы // переместить операцию Add-to-Enterlist, выше, за пределами критического раздела // защищенной _WaitSetlock. На практике это бесполезно. За исключением времени wait () и прерывает владелец монитора // - единственный поток, который захватывает _waitsetlock. Почти нет содержания // на _waitSetlock, поэтому не выгодно уменьшить длину критического раздела //} Thread :: SpinRelease (& _WaitSetlock); if (iterator! = Null && objectmonitor :: _ sync_notifications!Метод уведомления
Подобно методу уведомления, просто при извлечении очереди _WaitSet, это не первый, а все.
Метод ожидания
Метод ожидания заставляет поток подождать. Его соответствующий локальный метод - jvm_monitorwait, который косвенно вызывает ObjectSynchronizer :: Wait, что соответствует уведомлению. Это также метод ожидания, соответствующий вызову объекта ObjectMonitor. Этот метод длинный и не будет опубликован здесь. Вероятно, это создать объект ObjectWaiter, затем получить блокировку очереди _waitSet и добавить объект ObjectWaiter в очередь, а затем отпустите блокировку очереди. Кроме того, он выпустит соответствующий замок синхронизации, поэтому блокировка не ждет, пока не закончится блок синхронизированной синхронизации.
Jvm_entry (void, jvm_monitorwait (jnienv* env, jab handle, jlong ms)) jvmwrapper ("jvm_monitorwait"); Обработка obj (Thread, jnihandles :: resolve_non_null (handle)); assert (obj-> is_instance () || obj-> is_array (), "jvm_monitorwait должен применить к объекту"); JavathreadInobjectWaitState Jtiows (Thread, MS! = 0); if (jvmtiexport :: sup_post_monitor_wait ()) {jvmtiexport :: post_monitor_wait ((javathread *) поток, (oop) obj (), ms); } ObjectSynchronizer :: wate (obj, ms, check); jvm_endЗавершить метод
Этот метод используется, чтобы вызвать, когда объект переработан. Это поддерживается JVM. Метод завершения объекта ничего не делает по умолчанию. Если подкласс должен выполнить некоторую логическую обработку при переработке объекта, метод завершения можно переопределить.
Суммировать
Выше приведено все содержание этой статьи об анализе примера Java объекта с точки зрения исходного кода JDK. Я надеюсь, что это будет полезно для всех. Заинтересованные друзья могут продолжать ссылаться на другие связанные темы на этом сайте. Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это. Спасибо, друзья, за вашу поддержку на этом сайте!