2012-12-08 18 views
8

Objectクラスの実装方法が不思議です。内部状態が示されている方法の例Objectクラスはどのように実装されていますか(hashCodeや内部フィールドなどのメソッド)?

  1. 方法のhashCode()または(待機)
  2. 。 たとえば、イントリンシックなロックまたはオブジェクトのwait()を呼び出したスレッドを格納するためのデータ構造体。これらを見つけるために

は、私はOpenJDKのソースをダウンロードして掘るを開始しました。まず最初に、私が出会ったのlang \オブジェクト\ネイティブ\のJava \ \ openjdksrc \ JDK \ SRC \シェアでした。含む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); 
    } 
} 

と私の理解のために、方法[]配列は、オブジェクトのメソッドのネイティブ実装との間のマッピングを定義します。たとえば、ObjectのhashCode()はJVM_IHashCode関数にマップされます。 JVM_IHashCodeは、\ openjdksrc \ hotspot \ src \ share \ vm \ prims \ jvm.cppに実装されています。そして、私の最初の質問です。 これは既にVM自体の一部です(\ openjdksrc \ hotspot \ src \ share \ vmに既に定義されています)。 しかしJVM_IHashCodeのコードに移動することができます:オブジェクトがnullの場合、我々はここに0を返すのはなぜ

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 

私はNPEが投げられるべきだと思います。それ以外の場合、FastHashCodeは\ openjdksrc \ hotspot \ src \ share \ vm \ runtime \ synchronizer.cppから呼び出され、最終的には実際の値を計算する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クラス/構造体(?)は、ハッシュ値が格納されているmarkOopクラス/構造体(?)を有しています。 Funilly私はこれらのクラス/構造体を見つけることができません。私は見つけることができたすべてだった:

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

の\ openjdksrc \ホットスポット\のsrc \共有に\ VM \ privateフィールドにmarkOopを持っているようだ をoop.hpp \おっと。 しかし、実際にはコードの残りの部分で言及されている "oop"は何ですか? markOopの定義はどこにありますか?私が対応する発見した:\ VM \おっと\ markOop.hpp \ openjdksrc \ホットスポット\ SRC \共有で

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

が、それは列挙型の唯一いっぱいで、ハッシュ値ができるフィールドを見つけることができません保存する。 誰かが私の質問の少なくとも一部に答えることができたなら、私は非常に感謝します。ありがとう!

+0

はnull'なので 'のハッシュコードは、実際にゼロにすることになっていますjava.lang.Object) – int3

答えて

2

Javaオブジェクトのハッシュコードは、計算されるとオブジェクトヘッダーに格納されます。

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

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

ホットスポット/ srcに/共有/ VM /おっと/ markOopから。(http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/System.html#identityHashCode: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) 
// 
+1

参考:ここでの「OOP」は、「通常のオブジェクトポインタ」を意味します。 –

+0

ありがとう!私の頭の中にもう少し質問が現れました。あなたが参照しているウェブサイトでは、オブジェクトヘッダーが8バイト必要だと読んでいます。ここでは、16バイト(4バイトの各行* 4行)のように見えます。私はまた、いくつかのフィールドのサイズについて興味があります。なぜハッシュはわずか25ビットですか?そしてなぜロックが2ビットですか?私はそれがロックのためのちょうど1ビットを持つことで十分であると思う。そして、フィールドは何ですか?年齢、エポック、プロモーションビット? – Janek

+0

@ジャネク、良い質問があります。私は、 "正常"と "偏った"オブジェクト状態は相互に排他的だと思います。また、 "CMDフリー"と "CMS昇進"のために。世代別メモリ管理の実装には、年齢が使用されます。エポック?promo_bits?知りません。すべての答えはソースコードにあります。 :) – whunmr

関連する問題