Dalvik虚拟机JNI方法的注册过程分析 (八)

2014-11-24 10:58:08 · 作者: · 浏览: 10
ds,
jint nMethods)
{ return functions->RegisterNatives(this, clazz, methods, nMethods); }

......
} 这个函数定义在文件dalvik/libnativehelper/include/nativehelper/jni.h中。

从前面Dalvik虚拟机的运行过程分析一文可以知道,结构体JNIEnv的成员变量functions指向的是一个函数表,这个函数表又包含了一系列的函数指针,指向了在当前进程中运行的Dalvik虚拟机中定义的函数。对于结构体JNIEnv的成员函数RegisterNatives来说,它就是通过调用这个函数表中名称为RegisterNatives的函数指针来注册参数gMethods所描述的JNI方法的。

从前面Dalvik虚拟机的启动过程分析一文可以知道,上述函数表中名称为RegisterNatives的函数指针指向的是在Dalvik虚拟机内部定义的函数RegisterNatives,因此,接下来我们就继续分析它的实现。

Step 8. RegisterNatives


[cpp] static jint RegisterNatives(JNIEnv* env, jclass jclazz,
const JNINativeMethod* methods, jint nMethods)
{
JNI_ENTER();

ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
jint retval = JNI_OK;
int i;

......

for (i = 0; i < nMethods; i++) {
if (!dvmRegisterJNIMethod(clazz, methods[i].name,
methods[i].signature, methods[i].fnPtr))
{
retval = JNI_ERR;
}
}

JNI_EXIT();
return retval;
}

static jint RegisterNatives(JNIEnv* env, jclass jclazz,
const JNINativeMethod* methods, jint nMethods)
{
JNI_ENTER();

ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
jint retval = JNI_OK;
int i;

......

for (i = 0; i < nMethods; i++) {
if (!dvmRegisterJNIMethod(clazz, methods[i].name,
methods[i].signature, methods[i].fnPtr))
{
retval = JNI_ERR;
}
}

JNI_EXIT();
return retval;
} 这个函数定义在文件dalvik/vm/Jni.c中。

参数jclazz描述的是要注册JNI方法的类,而参数methods描述的是要注册的一组JNI方法,这个组JNI方法的个数由参数nMethods来描述。

函数RegisterNatives首先是调用函数dvmDecodeIndirectRef来获得要注册JNI方法的类对象,接着再通过一个for循环来依次调用函数dvmRegisterJNIMethod注册参数methods描述所描述的每一个JNI方法。注意,每一个JNI方法都由名称、签名和地址来描述。

接下来,我们就继续分析函数dvmRegisterJNIMethod的实现。

Step 9. dvmRegisterJNIMethod


[cpp] static bool dvmRegisterJNIMethod(ClassObject* clazz, const char* methodName,
const char* signature, void* fnPtr)
{
Method* method;
bool result = false;

if (fnPtr == NULL)
goto bail;

method = dvmFindDirectMethodByDescriptor(clazz, methodName, signature);
if (method == NULL)
method = dvmFindVirtualMethodByDescriptor(clazz, methodName, signature);
if (method == NULL) {
LOGW("ERROR: Unable to find decl for native %s.%s:%s\n",
clazz->descriptor, methodName, signature);
goto bail;
}

if (!dvmIsNativeMethod(method)) {
LOGW("Unable to register: not native: %s.%s:%s\n",
clazz->descriptor, methodName, signature);
goto bail;
}

if (method->nativeFunc != dvmResolveNativeMethod) {
/* this is allowed, but unusual */
LOGV("Note: %s.%s:%s was already registered\n",
clazz->descriptor, methodName, signature);
}

dvmUseJNIBridge(method, fnPtr);

LOGV("JNI-registered %s.%s:%s\n", clazz->descriptor, methodName,
signature);
result = true;

bail:
return result;
}

static bool dvmRegisterJNIMethod(ClassObject* clazz, const char* methodName,
const char* signature, void* fnPtr)
{
Method* method;
bool result = false;

if (fnPtr == NULL)
goto bail;

method = dvmFindDirectMethodByDescriptor(clazz, method