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

2014-11-24 10:58:08 · 作者: · 浏览: 11
函数调用规范,也就是所谓的ABI(Application Binary Interface),这是一个API(Application Programming Interface)不同的概念。ABI是在二进制级别上定义的一套函数调用规范,例如参数是通过寄存器来传递还是堆栈来传递,而API定义是一个应用程序编程接口规范。换句话说,API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译 ,而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。

为了使得运行在不同平台上的Dalvik虚拟机能够以统一的方法来调用JNI方法,这些Bridage函数使用了一个libffi库,它的源代码位于external/libffi目录中。Libffi是一个开源项目,用于高级语言之间的相互调用的处理,它的实现机制可以进一步参考http://www.sourceware.org/libffi/。

回到函数dvmUseJNIBridge中,它主要就是根据Dalvik虚拟机的启动选项来为即将要注册的JNI选择一个合适的Bridge函数。如果我们在Dalvik虚拟机启动的时候,通过-Xjnitrace选项来指定了要跟踪参数method所描述的JNI方法,那么函数dvmUseJNIBridge为该JNI方法选择的Bridge函数就为dvmTraceCallJNIMethod,否则的话,就再通过另外一个函数dvmSelectJNIBridge来进一步选择一个合适的Bridge函数。选择好Bridge函数之后,函数dvmUseJNIBridge最终就调用函数dvmSetNativeFunc来执行真正的JNI方法注册操作。

我们假设参数method所描述的JNI方法没有设置为跟踪,因此,接下来,我们就首先分析函数dvmSelectJNIBridge的实现,接着再分析函数dvmSetNativeFunc的实现。

Step 11. dvmSelectJNIBridge


[cpp] /*
* Returns the appropriate JNI bridge for 'method', also taking into account
* the -Xcheck:jni setting.
*/
static DalvikBridgeFunc dvmSelectJNIBridge(const Method* method)
{
enum {
kJNIGeneral = 0,
kJNISync = 1,
kJNIVirtualNoRef = 2,
kJNIStaticNoRef = 3,
} kind;
static const DalvikBridgeFunc stdFunc[] = {
dvmCallJNIMethod_general,
dvmCallJNIMethod_synchronized,
dvmCallJNIMethod_virtualNoRef,
dvmCallJNIMethod_staticNoRef
};
static const DalvikBridgeFunc checkFunc[] = {
dvmCheckCallJNIMethod_general,
dvmCheckCallJNIMethod_synchronized,
dvmCheckCallJNIMethod_virtualNoRef,
dvmCheckCallJNIMethod_staticNoRef
};

bool hasRefArg = false;

if (dvmIsSynchronizedMethod(method)) {
/* use version with synchronization; calls into general handler */
kind = kJNISync;
} else {
/*
* Do a quick scan through the "shorty" signature to see if the method
* takes any reference arguments.
*/
const char* cp = method->shorty;
while (*++cp != '\0') { /* pre-incr to skip return type */
if (*cp == 'L') {
/* 'L' used for both object and array references */
hasRefArg = true;
break;
}
}

if (hasRefArg) {
/* use general handler to slurp up reference args */
kind = kJNIGeneral;
} else {
/* virtual methods have a ref in args[0] (not in signature) */
if (dvmIsStaticMethod(method))
kind = kJNIStaticNoRef;
else
kind = kJNIVirtualNoRef;
}
}

return dvmIsCheckJNIEnabled() checkFunc[kind] : stdFunc[kind];
}

/*
* Returns the appropriate JNI bridge for 'method', also taking into account
* the -Xcheck:jni setting.
*/
static DalvikBridgeFunc dvmSelectJNIBridge(const Method* method)
{
enum {
kJNIGeneral = 0,
kJNISync = 1,
kJNIVirtualNoRef = 2,
kJNIStaticNoRef = 3,
} kind;
static const DalvikBridgeFunc stdFunc[] = {
dvmCallJNIMethod_general,
dvmCallJNIMethod_synchronized,
dvmCallJNIMethod_virtualNoRef,
dvmCallJNIMethod_staticNoRef
};
static const DalvikBridgeFunc checkFunc[] = {
dvmCheckCallJN