日韩性视频-久久久蜜桃-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制服丝袜 | 久久久久久色 | 精品人妻一区二区免费视频 | 国产cao| 日韩一区二区三区视频 | h片在线| 毛片网站有哪些 | 女警白嫩翘臀呻吟迎合 | 一区二区三区四区在线免费观看 | 快播日韩 | 素人fc2av清纯18岁 | 青青草免费观看视频 | 日产精品久久久 | 欧美精品大片 | 国产伦精品一区二区三区视频痴汉 | 超碰青草 | 在线观看无码精品 | 日韩动漫av | 爱爱一区 | 激情a | 国产玖玖| 中文字幕激情小说 | 国产艳妇疯狂做爰视频 | 久久精品久久久精品美女 | 末路1997全集免费观看完整版 | 自拍亚洲综合 | 性色综合| 国产精品第6页 | 91国偷自产中文字幕久久 | 亚洲午夜在线 | 久草www| 国产在线不卡视频 | 久久高清无码电影 | 成人免费视频国产 | 成人激情开心网 | 黄色网页大全 | 成人av高清在线观看 | 日日操夜夜骑 | 特黄aaaaaaa片免费视频 | 瑟瑟视频在线 | 一本加勒比北条麻妃 | 久久精品www人人爽人人 | a级片毛片 | 亚洲国产成人91porn | 在线免费观看小视频 | 亚洲成人高清在线 | 久久精品久久久久久久 | 黄色在线a | 福利视频二区 | 在线免费国产视频 | 亚洲av无码一区二区三区四区 | 老熟妇高潮一区二区三区 | 日本爽爽 | 中文字幕成人在线视频 | 婷婷狠狠| 天天看片天天干 | 成年人在线播放视频 | 天天操天天射天天爽 | 羞辱极度绿帽vk | 国v精品久久久网 | 天天干狠狠 | xxxxxx国产| 中文字幕无线精品亚洲乱码一区 | 日韩福利一区二区三区 | 亚洲成a人片77777精品 | 精品国产中文字幕 | 成人爽a毛片一区二区免费 日本高清免费看 | 黄色av片三级三级三级免费看 | 欧洲美女av| 日韩精品一线二线三线 | 日韩大片免费观看视频播放 | 91视频黄色| 国产精品sm调教免费专区 | 成人免费一区二区三区在线观看 | 五月婷婷激情四射 | 一区免费在线 | a男人天堂 | 在线无遮挡 | av合集| 欧美bbbbb性bbbbb视频 | 国产精品白嫩极品美女 | 免费中文av| 日日操日日干 | 女人叉开腿让男人桶 | 人人艹在线| 国产一区二区不卡在线 | 奇米影视77777 | 自拍偷拍欧美日韩 | 欧美日韩成人在线视频 | 欧美精品久久久久久久免费 | 欧美日本在线观看 | 精品人妻无码在线 | 日本三级韩国三级三级a级按摩 | 激情伊人网 | 91成人天堂久久成人 | 中国丰满人妻videoshd | 在线观看的免费 | 国产无套精品一区二区 |