Sono curioso di come viene implementata la classe Object. Per esempioCome viene implementata la classe Object (metodi come hashCode e campi interni)?
- un metodo hashCode() o attendere()
- Come è lo stato interno rappresentato. Ad esempio, un blocco instrinsic o la struttura dati per la memorizzazione di thread che hanno chiamato l'attesa dell'oggetto().
Per conoscere i prezzi, ho scaricato una fonte di OpenJDK e ha iniziato a scavare in. La prima cosa, mi sono imbattuto ero \ openjdksrc \ jdk \ src \ share \ nativo \ java lang \ Oggetto \. file C, che contiene, tra gli altri:
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/Object;", (void *)&JVM_Clone},
};
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls,
methods, sizeof(methods)/sizeof(methods[0]));
}
JNIEXPORT jclass JNICALL
Java_java_lang_Object_getClass(JNIEnv *env, jobject this)
{
if (this == NULL) {
JNU_ThrowNullPointerException(env, NULL);
return 0;
} else {
return (*env)->GetObjectClass(env, this);
}
}
e la mia comprensione, metodi array [] definisce una mappatura tra le implementazioni native di metodi dell'oggetto. Ad esempio, hashCode() dell'oggetto è mappato alla funzione JVM_IHashCode. JVM_IHashCode è implementato in \ openjdksrc \ hotspot \ src \ share \ vm \ prims \ jvm.cpp. E qui è la mia prima domanda. Perché questa è già una parte della VM stessa (è già definita in \ openjdksrc \ hotspot \ src \ share \ vm)? Ma consente di passare al codice di JVM_IHashCode:
JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
JVMWrapper("JVM_IHashCode");
// as implemented in the classic virtual machine; return 0 if object is NULL
return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
JVM_END
Perché se l'oggetto è nullo torniamo qui 0? Immagino che debba essere lanciato un NPE. In caso contrario, FastHashCode viene chiamato da \ openjdksrc \ hotspot \ src \ share \ vm \ runtime \ synchronizer.cpp e infine, in un determinato momento, viene chiamato get_next_hash che calcola il valore reale. Una volta calcolato, la domanda è dove è memorizzata?
intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
...CUT...
ObjectMonitor* monitor = NULL;
markOop temp, test;
intptr_t hash;
markOop mark = ReadStableMark (obj);
...CUT...
if (mark->is_neutral()) {
hash = mark->hash(); // this is a normal header
if (hash) { // if it has hash, just return it
return hash;
}
hash = get_next_hash(Self, obj); // allocate a new hash code
temp = mark->copy_set_hash(hash); // merge the hash code into header
// use (machine word version) atomic operation to install the hash
test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
if (test == mark) {
return hash;
}
// If atomic operation failed, we must inflate the header
// into heavy weight monitor. We could add more code here
// for fast path, but it does not worth the complexity.
}
...CUT...
return hash;
}
Quindi la programmazione orientata agli oggetti di classe/struct (?) ha un markOop classe/struttura (?) in cui è memorizzato il valore hash. Funilly non riesco a localizzare queste classi/strutture. Tutto quello che sono riuscito a trovare era:
class oopDesc {
friend class VMStructs;
private:
volatile markOop _mark;
...CUT...
in \ openjdksrc \ hotspot \ src \ share \ vm \ oops \ oop.hpp che sembra avere markOop in un settore privato. Ma allora cos'è realmente "oop" che si riferisce al resto del codice? E dove trovare la definizione markOop? Ho trovato un corrispondente:
class markOopDesc: public oopDesc
...CUT...
in \ openjdksrc \ hotspot \ src \ share \ vm \ oops \ markOop.hpp ma è pieno solo di enumerazioni e non riesco a trovare un campo in cui il valore hash può essere conservato Se qualcuno potesse rispondere almeno una parte delle mie domande , sarei molto grato. Grazie!
Il hashCode di 'null' si suppone infatti pari a zero: http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/System.html#identityHashCode (java.lang.Object) – int3