JNI是Java Native Interface的简写,即为Java本地调用。那么JNI在Android系统中起什么作用呢?答案是通过JNI,Java程序的函数可以调用Native中的函数(一般,Native用c/c++写的),比如说,上层获取电池相关信息;Native中的函数也可以调用Java中的函数,举一例,HDMI和耳机的侦测pin信息是从Java层传到Native,然后到Framework。
从分析frameworks\base\core\java\com\android\internal\os\RuntimeInit.java中的zygoteInitNative()函数开始,来分析它与JNI层的对应关系,看看它的声明:public static final native void zygoteInitNative(); 它带有Java关键字native,表示由JNI层来实现函数功能,也就是说在Java程序中声明该类型函数,前面需要带native修饰。
接下来,在sourceInsight中搜索zygoteInitNative,到frameworks\base\core\jni\AndroidRuntime.cpp,发现以下数据结构:
static JNINativeMethod gMethods[] = {
{ "finishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_finishInit },
{ "zygoteInitNative", "()V", //这个是我们要找的目标
(void*) com_android_internal_os_RuntimeInit_zygoteInit },
{ "isComputerOn", "()I",
(void*) com_android_internal_os_RuntimeInit_isComputerOn },
{ "turnComputerOn", "()V",
(void*) com_android_internal_os_RuntimeInit_turnComputerOn },
{ "getQwertyKeyboard", "()I",
(void*) com_android_internal_os_RuntimeInit_getQwertyKeyboard },
};
至此,有点眉目了,zygoteInitNative和(void*) com_android_internal_os_RuntimeInit_zygoteInit 是怎么建立关联的呢?当然要剖析JNINativeMethod 这个结构类型了,找到它的位置,在dalvik\libnativehelper\include\nativehelper\Jni.h 中:
typedef struct {
const char* name; //Java中native函数的名字,并不包含所属包的路径
const char* signature; //Java函数的签名信息,字符串表示的
void* fnPtr; //JNI层对应的函数指针,返回类型void*
} JNINativeMethod;
怎么来使用这个结构体呢?在AndroidRuntime.cpp中
//JNI注册
int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
gMethods, NELEM(gMethods)); //第二个参数表示是Java中的类。这里是RuntimeInit类
}
它调用jniRegisterNativeMethods函数,在dalvik\libnativehelper\JNIHelp.c 这个文件中:
/*
* Register native JNI-callable methods.
*
* "className" looks like "java/lang/String".
*/
int jniRegisterNativeMethods(JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
LOGV("Registering %s natives\n", className);
clazz = (*env)->FindClass(env, className);
if (clazz == NULL) {
LOGE("Native registration unable to find class '%s'\n", className);
return -1;
}
int result = 0;
if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
LOGE("RegisterNatives failed for '%s'\n", className);
result = -1;
}
(*env)->DeleteLocalRef(env, clazz);
return result;
}
分析上述函数,主要是两个函数。
1. jclass clazz = (*env)->FindClass(env, className); //className是对应的Java类名。查找函数所属具体的类。
2. (*env)->RegisterNatives(env, clazz, gMethods, numMethods);//调用JNIEnv的RegisterNatives函数,完成关联注册
注册后,在哪里被调用生效呢?
简要走下流程:
在frameworks\base\core\jni\AndroidRuntime.cpp中
1. static const RegJNIRec gRegJNI[] = {
.....
REG_JNI(register_com_android_internal_os_RuntimeInit),
.....
}
2. int AndroidRuntime::startReg(JNIEnv* env){
.....
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
......
}
3. void AndroidRuntime::start(const char* className, const bool startSystemServer){
.......
/*
* Register android functions.
*/
if (startReg(env) < 0) {
LOGE("Unable to register all android natives\n");
goto bail;
}
..........
}
4. void AndroidRuntime::start()
{
start("com.android.internal.os.RuntimeInit",
false /* Don't start the system server */);
/*
* 'startSystemServer == true' means runtime is obslete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
}
在启动android时候,就开始加载。