JNI动态注册

331 阅读5分钟

往期推荐

游戏内购“买买买”,不要钱

android逆向系列--java签名校验与反编译

11款android逆向实用工具

Smali文件详解

昨天给大家分享了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**

在这里插入图片描述