簡體   English   中英

JVM如何在運行時知道對象的類

[英]How does JVM know class of an object at runtime

jvm如何知道對象是運行時的實例。 我知道我們可以使用getClass方法來獲取類名,但getClass方法如何工作? Thx,Praveen。

答案? 魔法!

不,嚴重的是,它是實現定義的,並且JVM的實現不需要使用單個簡單技術,例如將類作為引用存儲在實例數據中的常量偏移量的字段中。 它所需要做的就是確保getClass方法可以按照文檔記錄的方式工作。 例如,通過轉義分析 ,JVM可以靜態地在堆上分配實例,因為它知道實例不會超過堆棧幀。 在這種情況下,它可以選擇將getClass()調用轉換為Class實例的直接加載,而不是方法調用! 類似地,因為getClass()在邏輯上是一個虛方法(我知道它是最終的,但它的返回值在任何給定類加載器的類的所有實例中都是常量,但對於每個不同的類是不同的,就好像它是一個返回常量的虛擬值),它可能會進行內聯緩存的類似優化。

我不知道JVM的細節,但在大多數面向對象的語言+運行時系統(Delphi,C ++,.NET)中,隱藏字段被添加到對象實例數據中,該數據指向對象實例的類型信息。

在將對象實例直接映射到外部數據結構時,必須小心這一點,因為對象實例數據中的隱藏類型信息或虛方法表指針將與外部數據結構中的字段失去對齊。

您通常可以通過查看對象實例的大小來查看此工件。 Sizeof()或等價物。 沒有聲明字段的對象仍將具有大於零的內存占用。 那就是類型信息魔術的來源。

如前面的答案所示,未指定實施。

為了了解實現的外觀,我研究了最近的Hotspot JVM的運行時部分。 在Hotspot中,每個對象都以標記詞(用於GC和其他用途)和一個klass指針開頭。 如果調用getClass,將調用Object.c中的本機實現:

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

GetObjectClass是JNI API的一部分。 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html)JNI GetObjectClass的內部實現實際上只是解析了對象指針,從類指針中讀取了klass ,並返回該類的Java表示形式:

JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
  JNIWrapper("GetObjectClass");

  HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);

  Klass* k = JNIHandles::resolve_non_null(obj)->klass();
  jclass ret =
    (jclass) JNIHandles::make_local(env, k->java_mirror());

  HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
  return ret;
JNI_END

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM