如何实现Object类(hashCode和内部字段等方法)?

时间:2012-12-08 13:07:18

标签: java object jvm

我很好奇Object类是如何实现的。例如

  1. 方法hashCode()或wait()
  2. 内部状态如何表示。 例如,一个内部锁或用于存储调用object的wait()的线程的数据结构。
  3. 为了找到这些,我已经下载了一个OpenJDK源并开始深入挖掘。首先,我遇到的是\ openjdksrc \ jdk \ src \ share \ native \ java \ lang \ Object.c文件,包含,其中包括:

    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);
        }
    }
    

    据我所知,methods []数组定义了Object方法的本机实现之间的映射。例如,Object的hashCode()被映射到JVM_IHashCode函数。 JVM_IHashCode在\ openjdksrc \ hotspot \ src \ share \ vm \ prims \ jvm.cpp中实现。这是我的第一个问题。 为什么这已经是VM本身的一部分(它已在\ openjdksrc \ hotspot \ src \ share \ vm中定义)? 但是让我们转到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
    

    为什么如果object为null我们返回0?我想应该抛出一个NPE。否则,从\ openjdksrc \ hotspot \ src \ share \ vm \ runtime \ synchronizer.cpp调用FastHashCode,并最终在某个时间点调用get_next_hash来计算实际值。 一旦计算出问题就在哪里存储?

        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;
        }
    

    所以oop类/ struct()有一个markOop类/结构(),其中存储了哈希值。 Funilly我找不到这些类/结构。我能找到的只有:

    class oopDesc {
      friend class VMStructs;
     private:
      volatile markOop  _mark;
    ...CUT...
    

    在\ openjdksrc \ hotspot \ src \ share \ vm \ oops \ oop.hpp中 这似乎在私人领域有markOop。 但那么真正的“oop”在其余的代码中引用了什么?哪里可以找到markOop定义?我找到了相应的:

    class markOopDesc: public oopDesc 
    ...CUT...
    

    在\ openjdksrc \ hotspot \ src \ share \ vm \ oops \ markOop.hpp中,但它只有枚举,无法找到可以存储哈希值的字段。 如果有人能够至少回答我问题的一部分,我将非常感激。谢谢!

1 个答案:

答案 0 :(得分:2)

Java对象的哈希码一经计算就存储在对象头中。

http://www.javamex.com/tutorials/memory/object_memory_usage.shtml

http://hunmr.blogspot.com/2012/08/java-performance-tunning.html

来自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)
//