问题
I am curious how is the Object class implemented. For example
- a method hashCode() or wait()
- How is the internal state represented. For instance, an instrinsic lock or the data structure for storing threads that called object's wait().
In order to find these out, I have downloaded a source of OpenJDK and started to dig in. First thing, I came across was \openjdksrc\jdk\src\share\native\java\lang\Object.c file, containing, among others:
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);
}
}
and to my understanding, methods[] array defines a mapping between the native implementations of Object's methods. So for example, Object's hashCode() is mapped to JVM_IHashCode function. The JVM_IHashCode is implemented in \openjdksrc\hotspot\src\share\vm\prims\jvm.cpp. And here is my first question. Why this is already a part of VM itself (it is defined already in \openjdksrc\hotspot\src\share\vm)? But lets move to the code of 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
Why if object is null we return here 0? I guess an NPE should be thrown. Otherwise, the FastHashCode is called from \openjdksrc\hotspot\src\share\vm\runtime\synchronizer.cpp and eventually at some point of time, the get_next_hash is called that calculates the real value. Once it is calculated the question is where it is stored?
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;
}
So the oop class/struct (?) has a markOop class/struct (?) where the hash value is stored. Funilly I can't locate these classes/structs. All I was able to find was:
class oopDesc {
friend class VMStructs;
private:
volatile markOop _mark;
...CUT...
in \openjdksrc\hotspot\src\share\vm\oops\oop.hpp which seems to have markOop in a private field. But then what really is "oop" which is refered in the rest of the code? And where to find markOop definition? I have found a corresponding:
class markOopDesc: public oopDesc
...CUT...
in \openjdksrc\hotspot\src\share\vm\oops\markOop.hpp but it is only full of enums and can't find a field where the hash value can be stored. If someone could answer at least a part of my questions I would be very grateful. Thanks!
回答1:
Java object's hash code is stored in object header, once it's calculated.
http://www.javamex.com/tutorials/memory/object_memory_usage.shtml
http://hunmr.blogspot.com/2012/08/java-performance-tunning.html
from hotspot/src/share/vm/oops/markOop.hpp
// The markOop describes the header of an object.
//
// Note that the mark is not a real oop but just a word.
// It is placed in the oop hierarchy for historical reasons.
//
// Bit-format of an object header (most significant first, big endian layout below):
//
// 32 bits:
// --------
// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
// size:32 ------------------------------------------>| (CMS free block)
// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
来源:https://stackoverflow.com/questions/13777731/how-is-the-object-class-implemented-methods-like-hashcode-and-internal-fields