객체는 모든 클래스의 부모 클래스입니다. 즉, Java의 모든 클래스는 객체 클래스에서 직접 또는 간접적으로 상속됩니다. 예를 들어, classa를 작성하면 명시 적으로 명시되지는 않지만 ExtendSobject의 기본값입니다.
다음 3 점 "..."는 몇 가지 불확실한 수의 매개 변수를 허용 할 수 있음을 나타냅니다. 오래된 글쓰기 방법은 Objectargs []이지만 새 버전의 Java에서 사용하는 것이 좋습니다. 예를 들어
publicvoidgetSomething(String...strings)(){}
객체는 Java의 모든 클래스의 부모 클래스입니다. 즉, 모든 클래스가 스스로 만들어 지든 시스템의 클래스에 관계없이 모든 클래스는 객체 클래스에서 상속됩니다. 즉, 모든 클래스는 어떤 경우에도 객체 클래스를 대체 할 수 있습니다. Rich의 교체 원칙에 따르면, 서브 클래스는 어떤 경우에도 부모 클래스를 대체 할 수 있지만, 부모 클래스는 반드시 하위 클래스를 대체 할 필요는 없습니다. 자바에서 자주 말하는 것은 실제로이 진실입니다! 객체 클래스는 OOP 아이디어에서 다형성, 상속, 캡슐화 및 추상화의 네 가지 주요 특성을 구현합니다!
객체 클래스는 데이터 유형이 아닌 모든 클래스의 기본 클래스입니다. JDK 문서를 쿼리하여이를 이해할 수 있습니다. 모든 클래스는 객체에서 상속됩니다.
객체 ... 객체이 매개 변수 정의는 불확실한 메소드 매개 변수의 경우 다형성 표현입니다. 즉,이 방법은 여러 매개 변수를 전달할 수 있으며 이러한 매개 변수의 수는 확실하지 않습니다. 이런 식으로, 방법 본문에서 해당 처리를 수행해야합니다. 객체는 기본 클래스이므로 개체 ... 오브젝트와 같은 매개 변수 양식을 사용하여 객체에서 상속 된 모든 객체를 매개 변수로 허용합니다. 이 방법은 실제로는 상대적으로 거의 사용되지 않아야합니다.
Object [] obj의 형태는 객체 배열로 구성된 매개 변수 양식입니다. 이것은이 방법의 매개 변수가 고정되어 있으며 객체 배열임을 의미합니다. 이 배열에 저장된 요소는 모든 클래스의 객체에서 상속 된 물체 일 수 있습니다.
이 기본적인 것들을 몇 번 더 읽는 것이 좋습니다. "Thinkinjava"
Java의 대상은 다른 모든 클래스의 부모 클래스입니다. 상속의 관점에서 볼 때, 그것은 최상위 수준의 루트이므로 부모 클래스가없는 유일한 클래스이기도합니다. 여기에는 getclass, hashcode, equals, clone, tostring, notify, wait 및 기타 일반적으로 사용되는 방법과 같은 객체에 일반적으로 사용되는 몇 가지 방법이 포함되어 있습니다. 따라서 다른 클래스가 객체를 상속 한 후에는 반복 구현없이 이러한 방법을 구현할 수 있습니다. 이러한 방법의 대부분은 기본 방법이며 다음과 같은 자세한 분석이 이루어집니다.
기본 코드는 다음과 같습니다.
공개 클래스 개체 {private static native void registernatives (); static {registernatives ();} public final native class <?> getClass (); public native int hashcode (); public boolean equals (object obj) {return (this == obj);} 보호 된 원시 대상 () trows clonenotspportedxception () {tostring (tostring) (tostring). GetClass (). getName () + " +" + " + integer.toHexString (hashCode ());} 공개 최종 기본 void notify (); public final void notifyall (); 공개 최종 기본 void wain (Long Timeout)은 인터럽트 최종 대기 (긴 시간 초 불법 행정 덱 션 ( "타임 아웃 값은 음수");} if (nanos <0 || nanos> 999999) {새로운 불법 불법 행위 렉싱 ( "Nanos Second -Timeout value of Range");} if (nanos> 0) {timeout ++;} (TimeOut); {대기 (0);} Protected Void Finalize () 던지기 가능 {}}등록 기간 방법
RegisterNatives 메소드는 정적 블록으로 수정되므로 객체 클래스가로드 될 때 메소드가 실행됩니다. 해당 로컬 방법은 다음과 같이 java_java_lang_object_registernatives입니다.
jniexport void jnicalljava_java_lang_object_registernatives (jnienv *env, jclass cls) {( *env)-> registernatives (env, cls, methods, methodof (methodof (methodof));}JninativeInterface_ 구조의 메소드를 간접적으로 호출하는 것을 볼 수 있습니다. 이는 간단하게 간단하게 간주 할 수 있습니다. 아마도 그 일은 아마도 로컬 기능을 갖춘 Java 레이어의 메소드 이름에 해당하므로 실행 엔진은 바이오 코드를 실행할 때 해당 관계 테이블을 기반으로 C/C ++ 기능을 호출 할 수 있습니다. 아래와 같이이 방법을 등록하십시오. 실행 엔진이 해시 코드 메소드를 실행하면 관계 테이블을 통해 JVM의 JVM_IHASHCODE 기능을 찾을 수 있습니다. () 또한 Java 레이어의 유형은 int 유형으로 변환되어야한다는 것을 알 수 있습니다. 이 매핑은 실제로 문자열을 함수 포인터에 매핑하는 것으로 간주 될 수 있습니다.
정적 jninativeMethod 메소드 [] = {{ "hashcode", "() i", (void *) & jvm_ihashcode}, { "wait", "(j) v", (void *) & jvm_monitorwait}, { "notify", ", (void *) & jvm_monitorn} "() 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, jobject this) {if (this == null) {jnu_thrownullpointerexception (env, null); 반환 0; } else {return (*env)-> getObjectClass (Env, this); }}그래서 여기서 우리는 주로 GetObjectClass 함수를 살펴 봅니다. C ++ 층의 Java 레이어의 해당 클래스는 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 :: cast (k)-> java_mirror ()); dtrace_probe1 (hotspot_jni, getobjectclass__return, ret); Ret; Jni_end를 반환합니다
해시 코드 방법
이전 RegisterNatives 메소드에서 몇 가지 로컬 메소드를 등록하면 해시 코드 메소드에 해당하는 함수가 JVM_IHASHCODE임을 알 수 있습니다.
JVM_ENTRY (JINT, JVM_IHASHCODE (jnienv* env, 작업 핸들)) JVMWRAPPER ( "jvm_ihashCode"); // 클래식 가상 머신에서 구현 된대로; 객체가 널 리턴 핸들 == null이면 0 반환? 0 : ObjectSynchronizer :: fasthashCode (스레드, jnihandles :: resolve_non_null (핸들)); jvm_end
해시 코드에 대해 생성 된 논리는 Synchronizer.cpp의 get_next_hash 함수에 의해 결정됩니다. 구현은 비교적 복잡합니다. 해시 코드의 다른 값을 기반으로 한 다른 생성 전략이 있으며, 마지막으로 해시 마스크를 사용하여 처리합니다.
정적 인라인 intptr_t get_next_hash (스레드 * self, oop obj) {intptr_t value = 0; if (hashcode == 0) {value = os :: random ();} else if (hashcode == 1) {intptr_t addrbits = intptr_t (obj) >> values = (addrrbits ^) ^. gvars.stwrandom;} else if (hashcode = 1) {value = 1; // 감도 테스트를 위해 value = 1; //} else if (hashcode == 3) {value = ++ gvars.hcsequence;} else if (hashcode == 4) {value = intptr_t (obj); << 11); self-> _ Hashstatex = self-> _ Hashstatey; self-> _ Hashstatey = self-> _ Hashstatez; self-> _ hashstatez = self-> _ Hashstatew; unsigned v = self-> _ hashstatew; v = (v >> 19) ^ (t ^ (t ^)) ; self-> _ hashstatew = v; value = v;} value & = markoopdesc :: hash_mask; if (value == 0) value = 0xbad; assert (value! = markoopdesc :: no_hash, "invariant"); tevent (hashcode : generate); 동등한 방법
이것은 비 국한 방법이며 판단 논리는 매우 간단하며 직접 == 비교입니다.
클론 방법
로컬 메소드 테이블에서, 우리는 클론 방법에 해당하는 로컬 기능이 JVM_Clone임을 알고 있습니다. 클론 방법은 주로 물체의 클로닝 함수를 구현하고 객체를 기반으로 동일한 새 객체를 생성합니다 (공통 클래스의 객체의 속성은 원시 유형 인 경우 값을 복제하지만 객체의 주소가 클로닝됩니다). Java 클래스의 복제를 구현하려면 클로닝 가능한 인터페이스를 구현해야합니다. if (! klass-> is_clonable ())은 인터페이스가 구현되었는지 확인합니다. 그런 다음 두 가지 상황에서 메모리 공간이 할당되는지 여부를 결정하십시오. 새로운 객체는 new_obj이며 복사 및 C ++ 레이어 데이터 구조가 New_Obj로 설정됩니다. 마지막으로 작업 유형으로 Java 레이어 객체 유형으로 변환됩니다.
jvm_entry (jobject, jvm_clone (jvm_clone (jnienv* env, job hands))) jvmwrapper ( "jvm_clone"); handle obj (스레드, jnihandles :: resolve_non_null (핸들)); const klasshandle klass (thread, obj-> klass (); (! klass-> is_clonable ()) {resourcemark rm (스레드); trash_msg_0 (vmsymbols :: java_lang_clonenotsupportedexception (), klass-> external_name ()); 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 :: conteoint_jlongs_atomic (jlong*), (jlong*) new_obj, (size_t) align_object_size (size) / heapwordsperlong); new_obj-> init_mark (); barrierset* bs = hep ()-> barrier_set (); Assert (bs-> has_write_regy_opt (), "장벽 세트는 write_region "); bs-> write_region (memregion ((heapword*) new_obj, size)); if (klass-> has_finalizer ()) {assert (assert (obj-> is_instance (),"instanceklass :: register_finalizer (new_obj)), check_null); jnihandles :: make_local (env, oop (new_obj)); jvm_end토스트 링 방법
논리는 클래스 이름 plus @ + 16 진수 해시 코드를 얻는 것입니다.
메소드 알림
이 방법은 스레드를 깨우는 데 사용되며 최종 수정 지침을 다시 작성할 수 없습니다. 해당 로컬 방법은 JVM_MonitorNotify입니다. Objectsynchronizer :: Notify는 결국 ObjectMonitor :: Notify (트랩)를 호출합니다. 이 프로세스는 ObjectSynChonizer가 현재 스레드에서 FreeObjectmonitor 객체를 가져 와서 실패하면 전역에서 가져 오려고 노력할 것입니다.
jvm_entry (void, jvm_monitornotify (jnienv* env, job hands)) jvmwrapper ( "jvm_monitornotify"); 핸들 OBJ (스레드, jnihandles :: resolve_non_null (핸들)); assert (obj-> is_instance () || obj-> is_array (), "jvm_monitornotify는 객체에 적용해야합니다"); ObjectSynChronizer :: Notify (OBJ, Check); JVM_END
ObjectMonitor 객체에는 대기 상태의 모든 스레드를 보유하고 ObjectWaiter 객체로 표시되는 _waitset 큐 객체가 포함되어 있습니다. 알림이 필요한 것은 먼저 _waitset 큐 잠금을 얻은 다음 _waitset 큐에서 첫 번째 Objectwaiter 객체를 제거한 다음 _entrylist 큐에 추가하는 것과 같은 다른 전략에 따라 객체를 처리하는 것입니다. 그런 다음 _waitset 큐 잠금을 해제하십시오. 동기화 된 해당 잠금을 해제하지 않으므로 동기화 된 동기화 블록이 끝날 때까지 잠금을 해제 할 수 있습니다.
void ObjectMonitor :: notify (traps) {check_owner (); if (_waitset == null) {tevent (empty -notify); return;} dtrace_monitor_probe (notify, this, this, object (), 스레드); int policy = knob_movenotifyee; stread :: spinacquire (& _waitsettlock, "); iterator = dequeuewaiter (); if (iterator! = null) {tevent (notify1-transfer); 보증 (iterator-> tstate == Objectwaiter :: ts_wait, "mavariant"); 보증 (iterator-> _ notified == 0, "invariant"); ObjectWaiter :: TS_ENTER;} iterator-> _ notified = 1; ObjectWaiter * list = _entryList; if (list! = null) {assert (list-> _ prev == null, "Invariant"); Assert (list-> tstate == objectWaiter :: ts_enter, "Inverater (list (list)"). ;} if (policy == 0) {// EntryListif (list == null) {iterator-> _ next = iterator-> _ prev = iterator;} else {list-> _ prev = iterator; iterator-> _ next = list; iterator-> _ prev = null; EntryListif (list == null) {iterator-> _ next = iterator-> _ prev = null; _entrylist = iterator;} else {// 고려 : 현재 꼬리를 찾으려면 // 입장 목록의 선형 시간이 필요합니다. 우리는 현재 dll.objectwaiter * tail; for (tail = list; tail-> _ next! = null; tail = tail-> _ next); Assert (tail! = null && tail-> _ next == null, "invariant"); a exerator; iterator; iterator; iterator; iterator; iterator; iterator; iterator; = null;}} else if (policy == 2) {// cxq // cxqif (list == null) {iterator-> _ next = iterator-> _ prev = null; _entrylist = iterator;} else {iterator-> tstate = Objecter :: ts_cxq; for (; _cxq; iterator-> _ next = front; if (atomic :: cmpxchg_ptr (iterator, & _cxq, front) {front) {break;}}}} else if (policy = 3) {// cxqiterator-> tstate = Objectwaiter :: ts_cxq; for (;; _cxq; if (tail == null) {iterator-> _ next = null; if (atomic :: cmpxchg_ptr (iterator, & _cxq, null) == null) {break;}} else {while (tail-> _ next! = null) tail-> _ tail-> _ tail-> _ next = iterater; ; iterator-> _ next = null; break;}}} else {parkevent * ev = iterator-> _ event; iterator-> tstate = ObjectWaiter :: ts_run; OrderAccess :: fence (); ev-> unpark ();} if (policy <4) {iterator-> witerator-> _waitsetLock은 입장 목록이 아닌 대기 대기열을 보호합니다. 우리는 // _waitsetlock에 의해 보호되는 임계 섹션 외부에서 add-to-enrylist 작동을 이동할 수 있습니다. 실제로 그것은 유용하지 않습니다. // wait () 타임 아웃과 인터럽트를 제외하고 모니터 소유자는 _waitsetlock을 잡는 유일한 스레드입니다. _waitsetlock의 내용이 거의 없으므로 // critical section의 길이를 줄이는 것이 수익성이 없습니다.} thread :: spinrelease (& _waitsetlock); if (iterator! = null && 객체 모터 ::Notifyall 메소드
Notify 메소드와 마찬가지로 _waitset 큐를 가져올 때는 첫 번째가 아니라 전부입니다.
대기 방법
대기 방법으로 스레드가 대기합니다. 해당 로컬 방법은 JVM_MonitorWait이며, 이는 간접적으로 ObjectSynChronizer :: 대기를 호출합니다. 또한 ObjectMonitor 객체를 호출하는 데 해당하는 대기 방법입니다. 이 방법은 길고 여기에 게시되지 않습니다. 아마도 Objectwaiter 객체를 만들고 _waitset 큐 잠금을 얻고 대상 객체를 큐에 추가 한 다음 대기열 잠금 장치를 해제하는 것일 수 있습니다. 또한 동기화 된 해당 잠금 잠금 장치가 해제되므로 동기화 된 동기화 블록이 끝날 때까지 잠금이 대기하지 않습니다.
jvm_entry (void, jvm_monitorwait (jnienv* env, 작업 핸들, Jlong MS)) jvmwrapper ( "jvm_monitorwait"); 핸들 OBJ (스레드, jnihandles :: resolve_non_null (핸들)); assert (obj-> is_instance () || obj-> is_array (), "jvm_monitorwait는 객체에 적용해야합니다"); javathreadinobjectwaitstate jtiows (스레드, ms! = 0); if (jvmtiexport :: duther_post_monitor_wait ()) {jvmtiexport :: post_monitor_wait ((javathread *) 스레드, (oop) obj (), ms); } ObjectSynchronizer :: WAIT (OBJ, MS, Check); jvm_end마무리 방법
이 방법은 물체가 재활용 될 때 호출됩니다. 이것은 JVM에 의해 지원됩니다. 객체의 최종 방법은 기본적으로 아무것도하지 않습니다. 객체를 재활용 할 때 서브 클래스가 일부 논리적 처리를 수행 해야하는 경우 최종 방법을 재정의 할 수 있습니다.
요약
위는 JDK 소스 코드의 관점에서 Java의 객체에 대한 Java 예제 분석에 대한이 기사의 모든 내용입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!