JNINativeMethod結構體及 系統 JNI 接口的註冊流程

zygote進程在啓動ART虛擬機後,會有一個註冊系統JNI接口的調用:

AndroidRuntime::start()中: 

.....
 if (startVm(&mJavaVM, &env) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
....

startReg(env)即是進行系統JNI接口的註冊.

    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }

gRegJNI的定義如下:

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    ......
    REG_JNI(register_android_os_Process),
    ......
}

register_jni_procs()的實現:

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
            ......
        }
    }
    return 0;
}

startReg(), 調用register_jni_procs(), 通過for循環,遍歷調用gRegJNI數組中的函數(通過指向函數的指針實現).

 

關於gRegJNI:

可以看到, gRegJNI是一個成員爲RegJNIRec類型的數組.RegJNIRec的定義如下:

#ifdef NDEBUG
    #define REG_JNI(name)      { name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
    };
#else
    #define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };
#endif

根據代碼推斷,宏開關NDEBUG是打開的,即RegJNIRec的實際定義爲:

    #define REG_JNI(name)      { name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
    };

即,RegJNIRec是一個結構體,該結構體有一個指向函數的指針成員,且該指針指向的函數的參數類型爲:JNIEnv*.

再看 gRegJNI[] 數組的一個成員:REG_JNI(register_android_os_Process),REG_JNI爲宏定義, 宏替換後的代碼應該爲:

{ register_android_os_Process}


上面已經分析, 註冊的過程,就是通過遍歷gRegJNI[] 數組,調用其成員中的函數指針指向的函數來實現. 而:

{ register_android_os_Process}

就是其中的結構體的成員,該結構體的唯一的成員爲一個函數指針:register_android_os_Process,跟蹤代碼,該函數位於android_util_Process.cpp中,完整定義:

int register_android_os_Process(JNIEnv* env)
{
    return RegisterMethodsOrDie(env, "android/os/Process", methods, NELEM(methods));
}
static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
                                       const JNINativeMethod* gMethods, int numMethods) {
    int res = AndroidRuntime::registerNativeMethods(env, className, gMethods, numMethods);
    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
    return res;
}

根據文件名(android_util_Process)可以推斷,該函數註冊的是Process相關的JNI接口, 具體哪些接口,由RegisterMethodsOrDie()的參數:methods指定.顯然, methods是一個結構體數組,且對應的結構體,就是  文章標題中提到的結構體: JNINativeMethod. 

 

該結構體對應一個JNI方法的相關信息

typedef struct {
    const char* name;     // java層對應的方法名稱
    const char* signature;// 該方法的返回值類型和參數類型
    void*       fnPtr;    // native中對應的函數指針
} JNINativeMethod;

 

android_util_Process指定的結構體數組 methods爲:

static const JNINativeMethod methods[] = {
    {"getUidForName",       "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName},
    {"getGidForName",       "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName},
    {"setThreadPriority",   "(II)V", (void*)android_os_Process_setThreadPriority},
    {"setThreadScheduler",  "(III)V", (void*)android_os_Process_setThreadScheduler},
    {"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground},
    {"setThreadPriority",   "(I)V", (void*)android_os_Process_setCallingThreadPriority},
    {"getThreadPriority",   "(I)I", (void*)android_os_Process_getThreadPriority},
    {"setThreadGroup",      "(II)V", (void*)android_os_Process_setThreadGroup},
    {"setProcessGroup",     "(II)V", (void*)android_os_Process_setProcessGroup},
    {"getProcessGroup",     "(I)I", (void*)android_os_Process_getProcessGroup},
    {"setSwappiness",   "(IZ)Z", (void*)android_os_Process_setSwappiness},
    {"setArgV0",    "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
    {"setUid", "(I)I", (void*)android_os_Process_setUid},
    {"setGid", "(I)I", (void*)android_os_Process_setGid},
    {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
    {"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
    {"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
    {"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
    {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},
    {"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
    {"readProcFile", "(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_readProcFile},
    {"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_parseProcLine},
    {"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
    {"getPss", "(I)J", (void*)android_os_Process_getPss},
    {"getPidsForCommands", "([Ljava/lang/String;)[I", (void*)android_os_Process_getPidsForCommands},
    //{"setApplicationObject", "(Landroid/os/IBinder;)V", (void*)android_os_Process_setApplicationObject},
    {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup},
    {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups},
};

以上便可以看到該接口註冊了哪些jni接口,相關接口在Java層便可通過jni調用,有些還是很眼熟的.

最終的註冊工作,是調用 AndroidRuntime.registerNativeMethods(env, className, gmethods,  numMethods)來實現。

系統JNI接口的註冊流程大致就是上面所述.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章