jvm在运行时如何知道一个对象是哪个类的实例。我知道我们可以使用getClass方法来获取类名,但是getClass方法是如何工作的呢? 谢谢, Praveen。
getClass
方法按照文档说明正常工作即可。例如,通过逃逸分析,JVM可以在堆上静态分配一个实例,因为它知道该实例不会超出堆栈帧的生命周期。在这种情况下,它可能选择将getClass()
调用转换为直接加载Class
实例,而不是方法调用!同样,由于getClass()
在逻辑上是一个虚拟方法(我知道它是final的,但它的返回值在来自任何给定类加载器的所有类的所有实例之间都是恒定的,但对于每个不同的类则不同,就像返回常量值的虚拟方法一样),因此它可能经历类似于内联缓存的优化。正如之前的答案所建议的那样,实现并没有具体说明。
为了了解实现可能的样子,我研究了最近 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
getClass()
方法将任何给定对象实例与Class
对象实例连接并没有真正关系。 - Barry Kelly