参照Openjdk源码分析Object.getClass()方法
1、找到openjdk中的java.lang.Object.class对应的本地c文件
openjdk\jdk\src\share\native\java\lang\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); } }
2、看到调用了JNI中的GetObjectClass
openjdk\hotspot\src\share\vm\prims\jni.cpp
JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj)) JNIWrapper("GetObjectClass"); #ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetObjectClass__entry, env, obj); #else /* USDT2 */ HOTSPOT_JNI_GETOBJECTCLASS_ENTRY( env, obj); #endif /* USDT2 */ /* 根据传入的java对象引用找到引用对象然后找到该对象类型的元数据 */ Klass* k = JNIHandles::resolve_non_null(obj)->klass(); /*根据元数据找到其镜像,也就是java程序中的Class对象实例*/ jclass ret = (jclass) JNIHandles::make_local(env, k->java_mirror()); #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectClass__return, ret); #else /* USDT2 */ HOTSPOT_JNI_GETOBJECTCLASS_RETURN( ret); #endif /* USDT2 */ return ret; JNI_END
JNIHandles::resolve_non_null将java中的对象引用转化为JVM中的对象实例
openjdk\hotspot\src\share\vm\runtime\jniHandles.hpp
inline oop JNIHandles::resolve_non_null(jobject handle) { assert(handle != NULL, "JNI handle should not be null"); oop result = *(oop*)handle; assert(result != NULL, "Invalid value read from jni handle"); assert(result != badJNIHandle, "Pointing to zapped jni handle area"); // Don't let that private _deleted_handle object escape into the wild. assert(result != deleted_handle(), "Used a deleted global handle."); return result; };
oop result = *(oop*)handle;这句代码是核心,主要意识就是将handle————传入的java引用先强转为JVM中的OOP【(oop*)handle】,然后根据指针地址找到所引用的对象实例【*(oop*)handle】。
在JVM中OOP是普通对象指针的意思,但实质上分为三部分(mark word、类型指针、实例数据)。
Klass* k = JNIHandles::resolve_non_null(obj)->klass();这句便是找到了对象实例所属类型的元数据
k->java_mirror()说明返回给java程序的Class对象是Klass元数据的镜像————OOP