亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解android平臺的jni—注冊native函數

發布時間:2021-10-14 15:30:13 來源:億速云 閱讀:149 作者:柒染 欄目:編程語言

這篇文章給大家介紹如何理解android平臺的jni—注冊native函數,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

注冊native函數有兩種方法:靜態注冊和動態注冊。

1、靜態注冊方法根據函數名找到對應的JNI函數:Java層調用函數時,會從對應的JNI中尋找該函數,如果沒有就會報錯,如果存在則會建立一個關聯聯系,以后在調用時會直接使用這個函數,這部分的操作由虛擬機完成。 靜態方法就是根據函數名來遍歷java和jni函數之間的關聯,而且要求jni層函數的名字必須遵循 特定的格式,其缺點在于:

 1)javah生成的jni層函數特別長;

 2)初次調用native函數時要根據名字搜索對應的jni層函數來建立關聯聯系,這樣影響效率。

2、動態注冊方法JNI 允許你提供一個函數映射表,注冊給Jave虛擬機,這樣Jvm就可以用函數映射表來調用相應的函數, 就可以不必通過函數名來查找需要調用的函數了。 Java與JNI通過JNINativeMethod的結構來建立聯系,它在jni.h中被定義,其結構內容如下: typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod; 第一個變量name是Java中函數的名字。 第二個變量signature,用字符串是描述了函數的參數和返回值 第三個變量fnPtr是函數指針,指向C函數。 當java通過System.loadLibrary加載完JNI動態庫后,緊接著會查找一個JNI_OnLoad的函數,如果有,就調用它, 而動態注冊的工作就是在這里完成的。 1)JNI_OnLoad()函數 JNI_OnLoad()函數在VM執行System.loadLibrary(xxx)函數時被調用,它有兩個重要的作用: 指定JNI版本:告訴VM該組件使用那一個JNI版本(若未提供JNI_OnLoad()函數,VM會默認該使用最老的JNI 1.1版),如果要使用新版本的JNI, 例如JNI 1.4版,則必須由JNI_OnLoad()函數返回常量JNI_VERSION_1_4(該常量定義在jni.h中) 來告知VM。 初始化設定,當VM執行到System.loadLibrary()函數時,會立即先呼叫JNI_OnLoad()方法,因此在該方法中進行各種資源的初始化操作最為恰當, 2)RegisterNatives RegisterNatives在AndroidRunTime里定義 syntax: jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)

3、在android中加入自定義的native函數JNI在Android層次結構中的作用

在Android中,主要的JNI代碼在以下的路徑中: Android源碼根目錄/frameworks/base/core/jni/ 這個路徑中的內容將被編譯成庫libandroid_runtime.so,這就是一個普通的動態庫,被放置在目標系統的/system/lib目錄中.除此之外,Android還包含其他的JNI庫,例如,媒體部分的JNI目錄frameworks/base/media/jni/中,被編譯成庫libmedia_jni.so. JNI中的各個文件實際上就是C++的普通文件,其命名一般和支持的Java類有對應關系。 這種關系是習慣上的寫法,而不是強制的。 1)注冊JNI方法 在Android源碼根目錄/frameworks/base/services/jni/目錄下有一個onload.cpp文件,加入 jni函數申明和jni函數注冊方法 #include "JNIHelp.h"  

#include "jni.h"  

#include "utils/Log.h"  

#include "utils/misc.h"  

namespace android {  

int register_android_server_AlarmManagerService(JNIEnv* env);  

int register_android_server_BatteryService(JNIEnv* env);  

int register_android_server_InputApplicationHandle(JNIEnv* env);  

int register_android_server_InputWindowHandle(JNIEnv* env);  

int register_android_server_InputManager(JNIEnv* env);  

int register_android_server_LightsService(JNIEnv* env);  

int register_android_server_PowerManagerService(JNIEnv* env);  

int register_android_server_UsbDeviceManager(JNIEnv* env);  

int register_android_server_UsbHostManager(JNIEnv* env);  

int register_android_server_VibratorService(JNIEnv* env);  

int register_android_server_SystemServer(JNIEnv* env);  

int register_android_server_location_GpsLocationProvider(JNIEnv* env);  

int register_android_server_connectivity_Vpn(JNIEnv* env);  

int register_android_server_HelloService(JNIEnv *env);  

//此處加入自定義jni函數申明};  

using namespace android;  

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)  

{  

 JNIEnv* env = NULL;  

 jint result = -1;  

 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  

 LOGE("GetEnv failed!");  

 return result;  

 }  

 LOG_ASSERT(env, "Could not retrieve the env!");  

 register_android_server_PowerManagerService(env);  

 register_android_server_InputApplicationHandle(env);  

 register_android_server_InputWindowHandle(env);  

 register_android_server_InputManager(env);  

 register_android_server_LightsService(env);  

 register_android_server_AlarmManagerService(env);  

 register_android_server_BatteryService(env);  

 register_android_server_UsbDeviceManager(env);  

 register_android_server_UsbHostManager(env);  

 register_android_server_VibratorService(env);  

 register_android_server_SystemServer(env);  

 register_android_server_location_GpsLocationProvider(env);  

 register_android_server_connectivity_Vpn(env);  

 register_android_server_HelloService(env); //jni方法注冊 

 return JNI_VERSION_1_4;  

}  

onload.cpp文件上部分為注冊函數的聲明,下部分為調用各種注冊函數,而這些注冊函數就是JNI方法的注冊函數! 正是通過這些注冊函數,上層才能調用注冊的JNI方法. 以register_android_server_HelloService為例,來看一個注冊函數的具體實現過程是如何的。 打開com_android_service_HelloService.cpp文件 2)加入注冊函數的實現代碼,如下: int register_android_server_HelloService(JNIEnv *env) {  

 return jniRegisterNativeMethods

(env, "com/android/server/HelloService", method_table, NELEM(method_table));  

}  

#其中jniRegisterNativeMethods

為注冊JNI方法函數,#此函數的第二個參數為對應著java類即HelloService.java的文件名,第三個參數為注冊的方法表 3)加入jni方法表  

static const JNINativeMethod method_table[] = {  

 {"init_native", "()Z", (void*)hello_init},  

 {"setVal_native", "(I)V", (void*)hello_setVal},  

 {"getVal_native", "()I", (void*)hello_getVal},  

};  

4)方法表內各個接口的實現代碼 static void hello_setVal(JNIEnv* env, jobject clazz, jint value) {  

val = value;  

 LOGI("Hello JNI: set value %d to device.", val);  

}  

static jint hello_getVal(JNIEnv* env, jobject clazz) {  

 LOGI("Hello JNI: get value %d from device.", val);  

 return val;  

 } 

static jboolean hello_init(JNIEnv* env, jclass clazz) {  

 LOGI("Hello JNI: initializing......");  

 return -1;  

 } 

完整代碼如下: namespace android {  

 int val; 

 static void hello_setVal(JNIEnv* env, jobject clazz, jint value) {  

val = value;  

 LOGI("Hello JNI: set value %d to device.", val);  

 }  

 static jint hello_getVal(JNIEnv* env, jobject clazz) {  

 LOGI("Hello JNI: get value %d from device.", val);  

 return val;  

 } 

static jboolean hello_init(JNIEnv* env, jclass clazz) {  

 LOGI("Hello JNI: initializing......");  

 return -1;  

 } 

 static const JNINativeMethod method_table[] = {  

 {"init_native", "()Z", (void*)hello_init},  

 {"setVal_native", "(I)V", (void*)hello_setVal},  

 {"getVal_native", "()I", (void*)hello_getVal},  

}; 

int register_android_server_HelloService(JNIEnv *env) {  

 return jniRegisterNativeMethods

(env, "com/android/server/HelloService", method_table, NELEM(method_table));  

}  

}

關于如何理解android平臺的jni—注冊native函數就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

淮阳县| 康定县| 吉安县| 湖口县| 上虞市| 阿克陶县| 清丰县| 静乐县| 谢通门县| 赤城县| 诸城市| 沿河| 东山县| 图木舒克市| 随州市| 天气| 永泰县| 建瓯市| 黄山市| 黄冈市| 株洲市| 伽师县| 昌江| 峨眉山市| 柳江县| 常州市| 平凉市| 荥经县| 濉溪县| 敦化市| 康保县| 璧山县| 岱山县| 会同县| 手游| 武义县| 个旧市| 安泽县| 胶州市| 通江县| 甘泉县|