日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android NDK 开发】JNI 动态注册 ( 动态注册流程 | JNI_OnLoad 方法 | JNINativeMethod 结构体 | GetEnv | RegisterNatives )

發布時間:2025/6/17 Android 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android NDK 开发】JNI 动态注册 ( 动态注册流程 | JNI_OnLoad 方法 | JNINativeMethod 结构体 | GetEnv | RegisterNatives ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • I . 動態注冊流程 ( 總結 )
        • II . JNI_OnLoad 方法
        • III . 被注冊的本地 C/C++ 方法參數
        • IV . JNINativeMethod 結構體 ( 核心重點 )
        • V . JavaVM 獲取 JNIEnv ( GetEnv )
        • VI . 動態注冊方法 RegisterNatives ( 核心重點 )
        • VII . 動態注冊流程完整代碼



I . 動態注冊流程 ( 總結 )



動態注冊流程 :


① 聲明 Java 層 Native 方法 : 在 Java 類中聲明 native 方法 ;

/*** 動態注冊 JNI 方法 , Java 方法*/public native void dynamicRegisterJavaMethod();public native int dynamicRegisterJavaMethod2(int i);

② 準備數據 JNINativeMethod methods[] 數組 : 其中定義了 Java 層方法與 Native 層方法的對應關系 ;

/*該數組中 , 每個元素都是一個 JNI 的 Native 方法JNINativeMethod 是結構體typedef struct {const char* name; //Java 中定義的 Native 方法名 , 注意這是一個 C 字符串const char* signature; //函數簽名 , 可以使用 javap 生成void* fnPtr; //C/C++ 中的 Native 函數簽名} JNINativeMethod;*/ static const JNINativeMethod methods[] = {{"dynamicRegisterJavaMethod", "()V", (void *)dynamicRegisterCMethod},{"dynamicRegisterJavaMethod2", "(I)I", (void *)dynamicRegisterCMethod2} };

③ 編寫 JNI_OnLoad 方法 : 在該方法中進行 JNI 方法動態注冊操作 ;

int JNI_OnLoad(JavaVM *vm , void *r){return JNI_VERSION_1_6; }

④ 獲取 JNIEnv 指針 : 調用 JavaVM 結構體的 GetEnv 方法 , 獲取 JNIEnv 指針 ;

//1 . 獲取 JNIEnv JNI 環境 , 需要從 JavaVM 獲取JNIEnv *env = nullptr;//2 . 調用 JavaVM / _JavaVM 結構體的 jint GetEnv(void** env, jint version) 方法// 返回值分析 : 動態注冊會返回一個結果// 如果 registerResult < 0 , 則動態注冊失敗// 如果 registerResult == 0 , 則動態注冊失敗int registerResult = vm->GetEnv( (void **) &env, JNI_VERSION_1_6 );

⑤ 獲取 Java 類 : 調用 JNIEnv 結構體的 FindClass 方法獲取 jclass 對象 ;

/*動態注冊的 Java 類名稱注意 : 包名類名之間使用 "/" 分割*/ static const char* className = "kim/hsl/onload/MainActivity";//獲取要動態注冊的 Java 類的 Class 對象jclass jclazz = env->FindClass(className);

⑥ 進行動態注冊 : 調用 JNIEnv 的 RegisterNatives 方法 , 進行正式注冊 ;

/*5 .正式注冊注冊方法解析 :jint RegisterNatives(jclass clazz, //要注冊的 Java 類const JNINativeMethod* methods, //JNI注冊方法數組jint nMethods //要注冊的 JNI 方法個數)sizeof(methods) / sizeof(JNINativeMethod) : 計算 JNINativeMethod methods[] 數組大小*/env->RegisterNatives(jclazz, methods, sizeof(methods) / sizeof(JNINativeMethod));

II . JNI_OnLoad 方法



1 . JNI_OnLoad 函數原型 : Java 類中調用 System.loadLibrary(“native-lib”) 代碼時 , 調用 JNI_OnLoad 方法 ;


① jni.h 中有該函數的聲明 :

/** Prototypes for functions exported by loadable shared libs. These are* called by JNI, not provided by JNI.*/ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);

② 參數列表說明 :

JavaVM* vm : 表示 Java 虛擬機 ;

void* reserved : 一般是 NULL ;


③ 返回值說明 : 返回當前 NDK 使用的 JNI 版本 ;

JNI 版本 中可選的有四個值 , 但是只能選擇返回后三個 JNI_VERSION_1_2 , JNI_VERSION_1_4 , JNI_VERSION_1_6 , 返回上述三個值任意一個沒有區別 ;

返回 JNI_VERSION_1_1 會報錯 ;

#define JNI_VERSION_1_1 0x00010001 #define JNI_VERSION_1_2 0x00010002 #define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_6 0x00010006

2 . JNI_OnLoad 方法常用操作 :


① 獲取 JavaVM 對象 ;

② 動態注冊 JNI 方法 ;



III . 被注冊的本地 C/C++ 方法參數



1 . 動態注冊對應的 C/C++ 本地方法 參數情況 :

① 傳遞參數 : 如果動態注冊的方法需要傳遞參數 , 需要加上 前面的 JNIEnv *env, jobject obj 兩個參數

jint dynamicRegisterCMethod2(JNIEnv *env, jobject obj, jint i){__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "dynamicRegisterCMethod2 : %d", i);return i + 1; }

② 不傳遞參數 : 如果不傳遞參數 , 就可以不添加任何參數 , 參數可以空著 ;

void dynamicRegisterCMethod(){__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "dynamicRegisterCMethod");}

IV . JNINativeMethod 結構體 ( 核心重點 )



1 . 結構體定義 : 該結構體定義了 C/C++ 方法 與 Java 方法的映射 ;


① const char* name : Java 中定義的 Native 方法名 , 注意這是一個 C 字符串

② const char* signature : 函數簽名 , 可以使用 javap 生成

③ void* fnPtr : C/C++ 中的 Native 函數指針

typedef struct {const char* name; // Java 中定義的 Native 方法名 , 注意這是一個 C 字符串const char* signature; // 函數簽名 , 可以使用 javap 生成void* fnPtr; // C/C++ 中的 Native 函數簽名 } JNINativeMethod;

2 . JNINativeMethod methods[] 數組 :


該數組是 JNI 方法動態注冊的參數 , 每個結構體表示了本地方法 與 Java 層方法的映射 ;

數組中有幾個元素 , 那么就映射了幾個方法 ;



V . JavaVM 獲取 JNIEnv ( GetEnv )



函數原型 : 從 Java 虛擬機 ( JavaVM ) 中獲取 JNI 運行環境 ( JNIEnv ) ;


① 參數說明 :

void** env : JNIEnv 的二級指針 ;

jint version : JNI 的版本 , 一般傳入 JNI_VERSION_1_6 ;


② 返回值說明 : 返回動態注冊結果 ;

動態注冊成功 : 返回 JNI_OK , 即 0 ;

動態注冊失敗 : 返回一個小于 0 的值 ;

struct _JavaVM {//封裝了 JNIInvokeInterface 結構體 , C 語言環境中調用該結構體中的方法const struct JNIInvokeInterface* functions;#if defined(__cplusplus)...//C++ 中封裝了 JNIInvokeInterface 的 GetEnv 方法jint GetEnv(void** env, jint version){ return functions->GetEnv(this, env, version); }... #endif /*__cplusplus*/ };

VI . 動態注冊方法 RegisterNatives ( 核心重點 )



1 . 函數原型 : 通過該 RegisterNatives 方法注冊 JNI 方法 ;


參數 :

  • jclass clazz : 要注冊方法所在的 Java 類
  • const JNINativeMethod* methods : Java 方法 與 本地方法的映射關系數組 ;
  • jint nMethods : 映射的方法個數 , 一般是 methods 數組元素個數 ;
struct _JNIEnv {/* _JNIEnv 結構體中封裝了 JNINativeInterface 結構體指針 */const struct JNINativeInterface* functions;...// 最終 調用的 還是 JNINativeInterface 結構體中封裝的 RegisterNatives 方法jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods){ return functions->RegisterNatives(this, clazz, methods, nMethods); }... }

2 . 代碼示例 :

//1 . Java 與 本地 方法映射數組 JNINativeMethod methods[] = {{"dynamicRegisterJavaMethod", "()V", (void *)dynamicRegisterCMethod},{"dynamicRegisterJavaMethod2", "(I)I", (void *)dynamicRegisterCMethod2} }; ... //2 . Java 類名 , 注意 : 包名類名之間使用 "/" 分割 char* className = "kim/hsl/onload/MainActivity"; ... //3 . 獲取要動態注冊的 Java 類的 Class 對象 jclass jclazz = env->FindClass(className); ... //4 . 正式注冊 env->RegisterNatives(jclazz, methods, sizeof(methods) / sizeof(JNINativeMethod));

VII . 動態注冊流程完整代碼



1 . Java 層代碼 :

package kim.hsl.onload;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.widget.TextView;public class MainActivity extends AppCompatActivity {// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);dynamicRegisterJavaMethod();dynamicRegisterJavaMethod2(250);}/*** 動態注冊 JNI 方法 , Java 方法*/public native void dynamicRegisterJavaMethod();public native int dynamicRegisterJavaMethod2(int i); }

2 . 本地代碼 ( C++ ) :

#include <jni.h> #include <string> #include <android/log.h>/*I . JNI_Onload 方法JNI_Onload 方法在 Java 層執行 System.loadLibrary("native-lib") 代碼時調用的方法主要是執行一些 JNI 初始化操作JNI_Onload 常見操作 :① 保存 JavaVM 對象 , 使用全局變量記錄該 Java 虛擬機對象② 動態注冊 : 動態注冊是該方法中最常見的操作JNI_Onload 參數說明 :JavaVM *vm : 代表了 Java 虛擬機void *r : 一般是 NULLJNI_Onload 返回值說明 :int 類型返回值代表了當前 NDK 使用的 JNI 版本JNI 版本 中可選的有四個值 , 但是只能選擇返回后三個 JNI_VERSION_1_2 , JNI_VERSION_1_4 , JNI_VERSION_1_6返回上述三個值任意一個沒有區別返回 JNI_VERSION_1_1 會報錯#define JNI_VERSION_1_1 0x00010001#define JNI_VERSION_1_2 0x00010002#define JNI_VERSION_1_4 0x00010004#define JNI_VERSION_1_6 0x00010006這四個值分別代表了 JDK 1.1 , 1.2 , 1.4 , 1.6 對應的 JNI 版本II . 動態注冊動態注冊 :動態注冊與靜態注冊 :靜態注冊 : 使用 Java_包名_類名_方法名(JNIEnv* env, jobject obj, ...) 方式進行注冊是靜態注冊動態注冊 : 將 C/C++ 中的本地方法 與 Java 中的方法對應起來 , 就需要使用動態注冊動態注冊 與 靜態注冊 : 沒有太大區別 , 都可以將 C/C++ 本地方法 與 Java 方法對應起來動態注冊流程 :① 聲明 Java 層 Native 方法② 準備數據 JNINativeMethod methods[] 數組③ 編寫 JNI_OnLoad 方法④ 獲取 JNIEnv 指針⑤ 獲取 Java 類⑥ 進行動態注冊*///使用 全局變量 記錄 Java 虛擬機對象 JavaVM *_vm;/*動態注冊對應的 C/C++ 本地方法如果動態注冊的方法需要傳遞參數 , 需要加上 前面的 JNIEnv *env, jobject obj 兩個參數如果不傳遞參數 , 就可以不添加任何參數不傳遞參數 , 參數可以空著*/ void dynamicRegisterCMethod(){__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "dynamicRegisterCMethod");}/*動態注冊對應的 C/C++ 本地方法如果動態注冊的方法需要傳遞參數 , 需要加上 前面的 JNIEnv *env, jobject obj 兩個參數如果不傳遞參數 , 就可以不添加任何參數傳遞參數 , 那么需要寫上 JNI 調用的完整參數*/ jint dynamicRegisterCMethod2(JNIEnv *env, jobject obj, jint i){__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "dynamicRegisterCMethod2 : %d", i);return i + 1; }/*該數組中 , 每個元素都是一個 JNI 的 Native 方法JNINativeMethod 是結構體typedef struct {const char* name; //Java 中定義的 Native 方法名 , 注意這是一個 C 字符串const char* signature; //函數簽名 , 可以使用 javap 生成void* fnPtr; //C/C++ 中的 Native 函數指針} JNINativeMethod;*/ static const JNINativeMethod methods[] = {{"dynamicRegisterJavaMethod", "()V", (void *)dynamicRegisterCMethod},{"dynamicRegisterJavaMethod2", "(I)I", (void *)dynamicRegisterCMethod2} };/*動態注冊的 Java 類名稱注意 : 包名類名之間使用 "/" 分割*/ static const char* className = "kim/hsl/onload/MainActivity";int JNI_OnLoad(JavaVM *vm , void* reserved){__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "JNI_Onload");//I . 存儲 Java 虛擬機對象//將 Java 虛擬機對象記錄到全局變量中_vm = vm;//II . 動態注冊//1 . 獲取 JNIEnv JNI 環境 , 需要從 JavaVM 獲取JNIEnv *env = nullptr;//2 . 調用 JavaVM / _JavaVM 結構體的 jint GetEnv(void** env, jint version) 方法// 返回值分析 : 動態注冊會返回一個結果// 如果 registerResult < 0 , 則動態注冊失敗// 如果 registerResult == 0 , 則動態注冊失敗int registerResult = vm->GetEnv( (void **) &env, JNI_VERSION_1_6 );//3 . 判斷結果 : 如果動態注冊 Native 方法失敗 , 直接退出if(registerResult != JNI_OK){return -1;}//4 . 獲取要動態注冊的 Java 類的 Class 對象jclass jclazz = env->FindClass(className);/*5 .正式注冊注冊方法解析 :jint RegisterNatives(jclass clazz, //要注冊的 Java 類const JNINativeMethod* methods, //JNI注冊方法數組jint nMethods //要注冊的 JNI 方法個數)sizeof(methods) / sizeof(JNINativeMethod) : 計算 JNINativeMethod methods[] 數組大小*/env->RegisterNatives(jclazz, methods, sizeof(methods) / sizeof(JNINativeMethod));return JNI_VERSION_1_6; }

3 . 執行結果 :

2020-02-08 14:01:51.142 13375-13375/? I/JNI_TAG: JNI_Onload 2020-02-08 14:01:51.299 13375-13375/? I/JNI_TAG: dynamicRegisterCMethod 2020-02-08 14:01:51.300 13375-13375/? I/JNI_TAG: dynamicRegisterCMethod2 : 250

總結

以上是生活随笔為你收集整理的【Android NDK 开发】JNI 动态注册 ( 动态注册流程 | JNI_OnLoad 方法 | JNINativeMethod 结构体 | GetEnv | RegisterNatives )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人深夜在线观看 | 性欧美大战久久久久久久久 | 国产伦一区二区三区 | av免费不卡 | 久久久999成人 | 国产在线观看av | www成年人| 成人性视频网站 | 好吊妞在线 | 2024男人天堂 | 女女互慰揉小黄文 | 亚洲日本中文字幕 | 久久久www成人免费无遮挡大片 | 国产偷v国产偷v亚洲高清 | 激情中文字幕 | 国产免费高清av | 黑人黄色一级片 | 欧美国产日韩视频 | 国产一区二区免费 | 午夜久久久久久久久 | 少妇熟女视频一区二区三区 | 97久久免费视频 | 97涩涩网 | 超碰在线日韩 | 色七七视频 | 日韩午夜激情电影 | 国产在线二区 | 18禁一区二区 | 一区二区色 | 91精品久久久久久久久久入口 | 黄页av | 久久在线精品视频 | 三级黄色免费片 | 欧美一区二区三区粗大 | 高清二区 | 亚洲视频在线观看网站 | 国产三级精品在线 | 韩国三级一区 | 国产毛片不卡 | 国产福利在线视频 | 伦理片一区二区 | 非洲黑人狂躁日本妞 | 国产午夜伦鲁鲁 | 爱爱小视频免费看 | 成人做受黄大片 | 久久精品国产亚洲AV成人婷婷 | 欧美激情影音先锋 | 在线观看视频亚洲 | 黄色免费片 | 中文二区 | 久久久999精品视频 国产在线xx | 成人免费在线播放 | 亚洲黄片一区 | 一级淫片免费看 | 一本久道视频一本久道 | h文在线观看 | 色小妹av| 中文字字幕一区二区三区四区五区 | 国产精品啊啊啊 | 新国产视频 | 91欧美一区二区三区 | 涩涩视频网站在线观看 | 日韩一本在线 | av午夜激情 | 91色交视频| 五月香蕉网 | 四虎精品久久 | 日韩成人免费在线 | 国产在线视频一区二区 | 欧美黄视频在线观看 | 国产精品18| 男人的天堂一区二区 | 牛人盗摄一区二区三区视频 | 国产视频资源 | 亚洲国产精品999 | 国产又爽又黄又嫩又猛又粗 | 91视色| 精品国产一区一区二区三亚瑟 | 国产又粗又大又爽视频 | 91成人在线免费 | 亚洲精品视频二区 | 欧美亚洲丝袜 | 精品久久久久久久免费人妻 | 玖草视频在线观看 | 真人真事免费毛片 | 在线播放第一页 | 中文字幕在线视频日韩 | 手机av在线网| 一级片视频在线观看 | 成年人看的免费视频 | 超碰公开在线观看 | 两性午夜免费视频 | 色播导航 | 日本a天堂 | 日韩免费在线视频观看 | 飘花影院伦理片 | 日本熟妇一区二区三区 | 精品资源成人 | 偷拍xxxx|