Lynx内核是由C++编写,方便跨平台使用。这样在Android端与Java层通信就需要使用JNI,Lynx在JNI层为了避免直接手写JNI注册代码以及反射调用Java的代码,使用自动化的方式来自动生成这部分代码。
JNI的注册方式
1. Java调用C/C++方法
通常Java调用C/C++方法的JNI方法注册分为静态注册和动态注册两种。
- 静态注册的方式
将Java中的Native方法在C/C++文件声明对应成Java_$PackageName_$MethodName(JNIEnv *env, args…) 完成完成静态注册。以Lynx代码中的自动化测试模块代码GTestDriver.java为例
package com.lynx.gtest;
...
public class GTestDriver {
...
//java native 方法
private static native int nativeRunGTestsNative(String[] gtestCmdLineArgs);
}
复制代码
对于C方法的编写如下
#include <jni.h>
...
JNIEXPORT jint Java_com_lynx_gtest_nativeRunGTestsNative(JNIEnv *env, jobjectArray gtestCmdLineArgs)
...
复制代码
从例子中可以看出静态注册的名字非常长,不便于书写。并且在初次调用的时候需要依据名字找到对应方法,对于大型工程中方法数多的情况下,效率低且易出错。
- 动态注册方式
通过在C/C++中声明一个JNINativeMethod nativeMethod[]数组,然后在JNI_OnLoad中调用RegisterNatives方法来完成动态注册。譬如上面的例子用动态注册的方式为:
#include <jni.h>
...
static jint RunGTestsNative(JNIEnv *env, jclass jcaller, jobjectArray gtestCmdLineArgs) {
....
}
static const JNINativeMethod kMethodsGTestDriver[] = {
{ "nativeRunGTestsNative",
"("
"[Ljava/lang/String;"
")"
"I", reinterpret_cast<void*>(RunGTestsNative) },
};
...
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
JNIEnv *env;
if ((*jvm) -> GetEnv(jvm, (