一.原理
当在系统中调用System.loadLibrary函数时,该函数会找到对应的动态库,
然后首先试图找到"JNI_OnLoad"函数,如果该函数存在,则调用它
JNI_OnLoad可以和JNIEnv的registerNatives函数结合起来,实现动态的函数替换

二. 实战

用ndk学习17的例子继续, 下面演示动态替换TestJni中的sayHello

jstring JNICALL Java_org_bing_testjni_MainActivity_sayHello
(JNIEnv* env, jobject obj, jstring name)
{
const char* pname = env->GetStringUTFChars(name, NULL);
string str_info = "Hello World:";
str_info += pname;
jstring ret_str = env->NewStringUTF(str_info.c_str());
// C文件使用(*env)->Fun(env,xxx,...)的方式传递
// (*env)->NewStringUTF(env, "Hello World");
return ret_str;

}

1.jni目录下新建一个cpp文件jni_replace.cpp
Android.mk中添加选项:
include $(CLEAR_VARS)
LOCAL_MODULE    := jni_replace
LOCAL_SRC_FILES := jni_replace.cpp
LOCAL_LDFLAGS += -llog

include $(BUILD_SHARED_LIBRARY)

2. 编写代码如下
#include "org_bing_testjni_MainActivity.h"
#include <stdio.h>
#include <string>
#include <android/log.h>
using namespace std;
__attribute__((visibility("hidden")))  jstring JNICALL sayHello (JNIEnv *, jobject, jstring);
__attribute__((visibility("hidden")))  JNINativeMethod g_Methods[] = {
"sayHello",
"(Ljava/lang/String;)Ljava/lang/String;",
(void*) sayHello
};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
__android_log_print(ANDROID_LOG_DEBUG, "__BING__", "JNI_OnLoad");
JNIEnv *pEnv = NULL;
//获取环境
jint ret = vm->GetEnv((void**) &pEnv, JNI_VERSION_1_6);
if (ret != JNI_OK) {
__android_log_print(ANDROID_LOG_DEBUG, "__BING__", "jni_replace JVM ERROR:GetEnv");
return -1;
}
jclass cls = pEnv->FindClass("org/bing/testjni/MainActivity");
if (cls == NULL) {
__android_log_print(ANDROID_LOG_DEBUG, "__BING__", "jni_replace:FindClass Error");
return -1;
}
//动态注册本地方法
ret = pEnv->RegisterNatives(cls, g_Methods,sizeof(g_Methods) / sizeof(g_Methods[0]));
if (ret != JNI_OK) {
__android_log_print(ANDROID_LOG_DEBUG, "__BING__", "jni_replace:FindClass Error");
return -1;
}
//返回java版本
return JNI_VERSION_1_6;
}
__attribute__((visibility("hidden")))  jstring JNICALL sayHello(JNIEnv* env,jobject obj, jstring name) {
const char* pname = env->GetStringUTFChars(name, NULL);
string str_info = "replace say hello function:";
str_info += pname;
jstring ret_str = env->NewStringUTF(str_info.c_str());
return ret_str;
}

3.运行结果
字符串被成功替换
三.NDK中使用Log
1.添加链接选项
LOCAL_LDFLAGS += -llog
这些库是在platform/android-xx/xxx/usr/lib目录下的
包含头文件:
#include <android/log.h>  
函数:
__android_log_print(ANDROID_LOG_DEBUG, "TAG", "Hello");  
日志输出选项是一个枚举
typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */

} android_LogPriority;

四.总结
这种JNI Onload的方法,在把Onload函数的在导出表里面抹掉
在动态初始化导出表
这样会增加逆向静态分析的成本
来自为知笔记(Wiz)

转载于:https://www.cnblogs.com/bingghost/p/5755662.html

ndk学习20: jni之OnLoad动态注册函数相关推荐

  1. NDK学习笔记-使用现有so动态库

    前面将的都是如何使用C/C++文件生成so动态库,那么在使用别人的so动态库的时候应该怎么做呢?这篇文章就是使用一个变声功能的动态库,完成对于以有so动态库的说明. 动态库来源 在互联网中,有着许许多 ...

  2. Android NDK学习:JNI中的数组、引用和异常的处理

    JNI的文档 https://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html JNI数组操作 调用数组 Java ...

  3. NDK学习笔记-JNI的引用

    JNI中的引用意在告知虚拟机何时回收一个JNI变量 JNI引用变量分为局部引用和全局引用 局部引用 局部引用,通过DeletLocalRef手动释放对象 原因 访问一个很大的Java对象,使用之后还用 ...

  4. Android JNI和NDK学习(5)--JNI分析API

    Java类型和本地类型对应 在如下情况下,需要在本地方法中应用java对象的引用,就会用到类型之间的转换: java方法里面将参数传入本地方法: 在本地方法里面创建java对象: 在本地方法里面ret ...

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

    文章目录 I . 动态注册流程 ( 总结 ) II . JNI_OnLoad 方法 III . 被注册的本地 C/C++ 方法参数 IV . JNINativeMethod 结构体 ( 核心重点 ) ...

  6. Android-NDK 动态注册与JNI线程

    文章目录 1.动态注册相比于静态注册的优点 2.JNI_OnLoad方法 3.动态注册的流程 3.1编写需要动态注册的方法 3.2增加结构体数组 3.3编写JNI_OnLoad方法 4.JNI中子线程 ...

  7. 【我的C语言学习进阶之旅】介绍一下NDK开发中关于JNI函数的两种注册方式:静态注册和动态注册

    目录 一.要介绍本篇博客的原因 二.静态注册 2.1 实现原理 2.2 实现过程 2.3 弊端 2.4 示例 三.动态注册 3.1 实现原理 3.2 实现过程 3.3 优点 3.4 示例 一.要介绍本 ...

  8. 安卓逆向_15( 三 ) --- Android NDK 开发【 jni 静态注册、JNI_OnLoad 动态注册】

    Android Studio开发JNI示例:https://blog.csdn.net/wzhseu/article/details/79683045 JNI_动态注册_静态注册.zip : http ...

  9. NDK 开发之 JNI 方法静态注册与动态注册

    1 前言 上文说到,进行 NDK 开发的时候,我们首先需要把 Java 方法声明为 native,然后编写对应的 C/C++ 代码,并编译成为动态链接库,在调用 Java 方法前加载动态链接库即可调用 ...

最新文章

  1. StackOverFlow上你没看过的7个Java最佳答案
  2. 第2.02节 下载源码
  3. Python实现不规则txt文本数据读取并转换为csv文本
  4. BZOJ4698: Sdoi2008 Sandy的卡片
  5. 如何手动更新Kafka中某个Topic的偏移量
  6. PPT模板(淘宝花钱买来的,免费分享给大家)
  7. [Unity] 在 3DsMax 中将骨骼调整为适应 Unity 的 Humanoid 的结构的记录
  8. 专家论道,把脉数据库技术发展新方向
  9. 如何对xgboost模型进行优化
  10. Python Qt GUI设计简介、环境下载和安装(基础篇—1)
  11. h2ouve下载 insyde_神舟tx6zx6gx9tx9蓝天模具解锁bios高级菜单
  12. LeaRun快速开发平台:企业供应链管理系统解决方案
  13. 最容易理解的ConViT: Improving Vision Transformerswith Soft Convolutional Inductive Biases
  14. .frx文件扩展的细节-文件扩展名 数据库
  15. Linux系统数据文件和信息
  16. 1005. F.Snowy Roads最小生成树Kruskal算法
  17. [Algorithm]Bubble_冒泡算法代码实现
  18. 【实战技能】Google I/O 2022大会AI/ML给开发者的启发
  19. win7工作组看不到“其他电脑”的解决方法
  20. H.266/VVC中的帧内子划分(Intra Sub-Partitions,ISP)

热门文章

  1. ASP.NET MVC 4应用程序文件夹
  2. CoreAnimation编程指南(八)事务 转自:http://www.dreamingwish.com/
  3. Flash和HTML5那点事:后者拿什么取代Flash?
  4. Mr.J-- jQuery学习笔记(十二)--移入移出事件电影排行榜小demo
  5. Mr.J--C语言头函数的建立(附严薇敏《数据结构》线性表代码)
  6. MITx - 6.00.1x 笔记(4) Good Programming Practices
  7. eclipsenbsp;mavennbsp;pluginamp;n…
  8. 数学公式(待慢慢总结)
  9. 5月份美网络游戏用户达8700万 同比增长22%
  10. node soket.io + express + vue-soket.io 之间实现通信