浅谈JNI

           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时候,就开始加载。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值