JNI動態註冊

往期推薦

JNI靜態註冊

Android NDK–JNI接口

如何編譯可執行程序

Android NDK–瞭解c語言

昨天給大家分享了JNI靜態註冊,對JNI靜態註冊有了一定的瞭解。JNI靜態註冊每一次添加新的native方法,都需要執行javah命令生成頭文件,而更快捷的方法就是不需要頭文件的JNI動態註冊。

昨天定義了一個native方法來演示JNI靜態註冊流程,今天需要再定義兩個native方法來演示JNI動態註冊流程。

一:定義native方法

1.打開eclipse工具,找到演示JNI靜態註冊時創建的「yijindaxue」工程,找到「src」=>「com.yijindaxue」目錄下「MainActivity.java」文件,雙擊打開該文件,如下圖所示。

在這裏插入圖片描述

2.在「MainActivity.java」文件中再定義兩個native方法,獲取int類型的值和char類型的字符。如果文件名字前出現「*「,表示該文件沒有保存,需要CTRL+S保存,如下圖所示。

在這裏插入圖片描述

3.native方法定義完成後,打開「jni.h」文件,瞭解JNI動態註冊的相關內容。

二: jni.h文件

JNI_OnLoad函數的執行時機非常早,它的格式爲:

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);

它返回的是一個jint類型的值,第一個跟第二個參數是JavaVM和 reserved ,默認兩個值即可,如下圖所示。

在這裏插入圖片描述

以下四條信息是ndk開發所使用的版本信息,結合情況使用即可。

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

事件就是處理事件信息所用到的常量信息,後面則是對應的數值,0代表正確,-1代表錯誤,-2代表JVM的派生線程,-3代表JNI版本不一致,如下所示。

#define JNI_OK (0)
#define JNI_ERR (-1)
#define JNI_EDETACHED (-2)
#define JNI_EVERSION (-3)

返回這個參數,需要判斷jvm與JNI是否版本一致,如下圖所示。

在這裏插入圖片描述

查看「jni.h」文件後,瞭解與JNI動態註冊相關的內容,接下來編寫相應的C代碼。

三:編寫C代碼

1.在「yijindaxue」工程中找到「jni」目錄下的「yijindaxue.c」文件,雙擊打開該文件,如下圖所示。

在這裏插入圖片描述

2.將「jni.h」頭文件中的「JNIEXPORT void JNICALL JNI_OnLoad ( JavaVM* vm, void* reserved);」複製粘貼至箭頭所指位置,如下圖所示。

在這裏插入圖片描述

3.刪除「;」,並添加{},如下圖所示。

在這裏插入圖片描述

4.在JNI_OnLoad函數中編寫相應的代碼,如下圖所示。

在這裏插入圖片描述

5.編寫代碼共分五個步驟操作:

  • 第一步:return JNI_VERSION_1_4; JNI_OnLoad函數的返回值是一個jint類型,返回的是JNI版本信息。
  • 第二步:聲明一個類型爲JNIEnv*的指針變量env。
  • 第三步:調用GetEnv函數獲取JNIEnv*。 - 第四步:調用FindClass函數獲取對應的類。
  • 第五步:調用RegisterNatives函數註冊對應的native方法。該函數需要傳入四個參數,第一個參數和第二個參數之前已經獲取到了,第三個參數是方法結構體數組,第四個參數是動態註冊native方法個數。

JNI_OnLoad函數的相關代碼編寫完成,它就是JNI動態註冊的模板,後續使用時只需要修改相應函數的參數即可。

第六步:定義方法結構體數組,編寫相應的代碼,如下圖所示。

在這裏插入圖片描述

6.方法結構體數組定義完成後,編寫對應的C函數,如下圖所示。

在這裏插入圖片描述

探究:爲什麼沒有執行javah命令生成頭文件的操作?

沒有執行javah命令生成頭文件的操作,是因爲JNI動態註冊是通過RegisterNatives函數來註冊Java層native方法與底層C函數的對應關係,這樣就可以省略生成頭文件的操作。

Java層的native方法對應的底層C代碼已經編寫完成,接下來在MainActivity類中找到onCreate方法,編寫相應的代碼調用native方法,如下圖所示。

在這裏插入圖片描述

四:編譯動態鏈接庫

1.在「yijindaxue」工程下,選中jni目錄,右鍵選擇最後一項properties點擊該選項彈出彈窗,複製「Location」對應的值,是文件路徑(D:\Android \data\yijindaxue\jni),複製成功後關閉對話框,如下圖所示。

在這裏插入圖片描述

2.點擊左下角「windows」圖標,輸入「cmd」命令打開窗口,輸入「D:」切換到D盤,執行「cd D:\Android\data\yijindaxue\jni」命令進入jni目錄,緊接着執行「ndk-build」命令生成動態鏈接庫「.so」文件,如下圖所示。

在這裏插入圖片描述

3.打開雷電模擬器,運行應用程序:選中「yijindaxue」工程=>右鍵選擇Run As選項=> 點擊Android Application。

小結:

通過今天的分享,我們掌握了JNI動態註冊流程:

1、定義native方法。聲明java方法時使用關鍵字「native進行修飾。
2、閱讀「jni.h」文件,瞭解與JNI動態註冊有關的內容。
3、在「yijindaxue.c」文件中編寫對應的C代碼流程。

  • 第一步: JNI_OnLoad函數的返回值是一個jint類型,返回的是JNI版本信息。
  • 第二步:聲明一個類型爲JNIEnv*的指針變量env。
  • 第三步:調用GetEnv函數獲取JNIEnv*。
  • 第四步:調用FindClass函數獲取對應的類。
  • 第五步:調用RegisterNatives函數註冊對應的native方法。
  • 第六步:定義方法結構體數組,編寫相應的代碼

4、使用NDK工具編譯.c文件生成動態鏈接庫.so文件。
5、運行該程序。

好啦,今天的分享到這就完了, 如果你有什麼疑惑或者不懂得地方,可以在評論區評論噢

如果你也對安卓逆向感興趣。可以加下方的羣,大家一起討論問題,或者掃描下方二維碼關注公衆號,關注回覆 「安卓逆向」 獲取免費教程

安卓逆向交流學習:1139349849
vx:Yjxiaox

在這裏插入圖片描述