注册native函数有两种方法:静态注册和动态注册。
1、静态注册方法
根据函数名找到对应的JNI函数:Java层调用函数时,会从对应的JNI中寻找该函数,如果没有就会报错,如果存在则会建立一个关联联系,以后在调用时会直接使用这个函数,这部分的操作由虚拟机完成。
静态方法就是根据函数名来遍历java和jni函数之间的关联,而且要求jni层函数的名字必须遵循
特定的格式,其缺点在于:
1)javah生成的jni层函数特别长;
2)初次调用native函数时要根据名字搜索对应的jni层函数来建立关联联系,这样影响效率。
2、动态注册方法
JNI 允许你提供一个函数映射表,注册给Jave虚拟机,这样Jvm就可以用函数映射表来调用相应的函数,
就可以不必通过函数名来查找需要调用的函数了。
Java与JNI通过JNINativeMethod的结构来建立联系,它在jni.h中被定义,其结构内容如下:
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
第一个变量name是Java中函数的名字。
第二个变量signature,用字符串是描述了函数的参数和返回值
第三个变量fnPtr是函数指针,指向C函数。
当java通过System.loadLibrary加载完JNI动态库后,紧接着会查找一个JNI_OnLoad的函数,如果有,就调用它,
而动态注册的工作就是在这里完成的。
1)JNI_OnLoad()函数
JNI_OnLoad()函数在VM执行System.loadLibrary(xxx)函数时被调用,它有两个重要的作用:
指定JNI版本:告诉VM该组件使用那一个JNI版本(若未提供JNI_OnLoad()函数,VM会默认该使用最老的JNI 1.1版),如果要使用新版本的JNI,
例如JNI 1.4版,则必须由JNI_OnLoad()函数返回常量JNI_VERSION_1_4(该常量定义在jni.h中) 来告知VM。
初始化设定,当VM执行到System.loadLibrary()函数时,会立即先呼叫JNI_OnLoad()方法,因此在该方法中进行各种资源的初始化操作最为恰当,
2)RegisterNatives
RegisterNatives在AndroidRunTime里定义
syntax:
jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)
3、在android中加入自定义的native函数
JNI在Android层次结构中的作用如下图所示:

   
在Android中,主要的JNI代码在以下的路径中:
Android源码根目录/frameworks/base/core/jni/
这个路径中的内容将被编译成库libandroid_runtime.so,这就是一个普通的动态库,被放置在目标系统的/system/lib目录中.除此之外,Android还包含其他的JNI库,例如,媒体部分的JNI目录frameworks/base/media/jni/中,被编译成库libmedia_jni.so.
JNI中的各个文件实际上就是C++的普通文件,其命名一般和支持的Java类有对应关系。
这种关系是习惯上的写法,而不是强制的。
1)注册JNI方法
在Android源码根目录/frameworks/base/services/jni/目录下有一个onload.cpp文件,加入 jni函数申明和jni函数注册方法
#include "JNIHelp.h"   
#include "jni.h"   
#include "utils/Log.h"   
#include "utils/misc.h"   
namespace android {  
int register_android_server_AlarmManagerService(JNIEnv* env);  
int register_android_server_BatteryService(JNIEnv* env);  
int register_android_server_InputApplicationHandle(JNIEnv* env);  
int register_android_server_InputWindowHandle(JNIEnv* env);  
int register_android_server_InputManager(JNIEnv* env);  
int register_android_server_LightsService(JNIEnv* env);  
int register_android_server_PowerManagerService(JNIEnv* env);  
int register_android_server_UsbDeviceManager(JNIEnv* env);  
int register_android_server_UsbHostManager(JNIEnv* env);  
int register_android_server_VibratorService(JNIEnv* env);  
int register_android_server_SystemServer(JNIEnv* env);  
int register_android_server_location_GpsLocationProvider(JNIEnv* env);  
int register_android_server_connectivity_Vpn(JNIEnv* env);  
int register_android_server_HelloService(JNIEnv *env);  //此处加入自定义jni函数申明
};  
using namespace android;  
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)  
{  
JNIEnv* env = NULL;  
jint result = -1;  
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
LOGE("GetEnv failed!");  
return result;  
}  
LOG_ASSERT(env, "Could not retrieve the env!");  
register_android_server_PowerManagerService(env);  
register_android_server_InputApplicationHandle(env);  
register_android_server_InputWindowHandle(env);  
register_android_server_InputManager(env);  
register_android_server_LightsService(env);  
register_android_server_AlarmManagerService(env);  
register_android_server_BatteryService(env);  
register_android_server_UsbDeviceManager(env);  
register_android_server_UsbHostManager(env);  
register_android_server_VibratorService(env);  
register_android_server_SystemServer(env);  
register_android_server_location_GpsLocationProvider(env);  
register_android_server_connectivity_Vpn(env);  
register_android_server_HelloService(env); //jni方法注册
return JNI_VERSION_1_4;  
}  
onload.cpp文件上部分为注册函数的声明,下部分为调用各种注册函数,而这些注册函数就是JNI方法的注册函数! 正是通过这些注册函数,上层才能调用注册的JNI方法.
以register_android_server_HelloService为例,来看一个注册函数的具体实现过程是如何的。
打开com_android_service_HelloService.cpp文件
2)加入注册函数的实现代码,如下:
int register_android_server_HelloService(JNIEnv *env) {  
return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));  
}  
#其中jniRegisterNativeMethods为注册JNI方法函数,
#此函数的第二个参数为对应着java类即HelloService.java的文件名,第三个参数为注册的方法表
3)加入jni方法表
static const JNINativeMethod method_table[] = {  
{"init_native", "()Z", (void*)hello_init},  
{"setVal_native", "(I)V", (void*)hello_setVal},  
{"getVal_native", "()I", (void*)hello_getVal},  
};  
4)方法表内各个接口的实现代码
static void hello_setVal(JNIEnv* env, jobject clazz, jint value) {  
val = value;  
LOGI("Hello JNI: set value %d to device.", val);  
}  
static jint hello_getVal(JNIEnv* env, jobject clazz) {  
LOGI("Hello JNI: get value %d from device.", val);  
return val;  
static jboolean hello_init(JNIEnv* env, jclass clazz) {  
LOGI("Hello JNI: initializing......");  
return -1;        
完整代码如下:
namespace android
{
int val;
static void hello_setVal(JNIEnv* env, jobject clazz, jint value) {  
val = value;  
LOGI("Hello JNI: set value %d to device.", val);  
}  
static jint hello_getVal(JNIEnv* env, jobject clazz) {  
LOGI("Hello JNI: get value %d from device.", val);  
return val;  
static jboolean hello_init(JNIEnv* env, jclass clazz) {  
LOGI("Hello JNI: initializing......");  
return -1;        
static const JNINativeMethod method_table[] = {  
{"init_native", "()Z", (void*)hello_init},  
{"setVal_native", "(I)V", (void*)hello_setVal},  
{"getVal_native", "()I", (void*)hello_getVal},  
}; 
int register_android_server_HelloService(JNIEnv *env) {  
return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));  
}  
}
本文欢迎转载,转载请注明出处与作者 
出处:http://blog.sina.com.cn/staratsky
作者:流星

转载于:https://www.cnblogs.com/aiguozhe/p/5355241.html

深入了解android平台的jni---注册native函数相关推荐

  1. java类sample是公共的_应在名samle.java的文件_Andoid NDK编程 1 - 注册native函数

    打算对Android的NDK的开发做一总结,首先是JNI部分,接下来是NDK的内容.今天首先介绍一下JNI的第一部分:注册native函数. 当java代码中执行native的代码时候,首先是通过一定 ...

  2. 【Android 逆向】ART 脱壳 ( InMemoryDexClassLoader 脱壳 | DexFile 构造函数及相关调用函数 | Android 源码中查找 native 函数 )

    文章目录 一.DexFile 构造函数 二.DexFile.openInMemoryDexFile 函数 三.Android 源码中查找 native 函数 一.DexFile 构造函数 上一篇博客 ...

  3. android 动态注册,Android studio实现动态注册Native方法

    说到动态就有静态,但是静态的注册在上一篇文章中已经包含了,这里就不在赘述了,直接说动态实现. 这里我们分步走. 1.创建android工程 选择普通工程 项目命名 不出意外,项目一会就建立完成. 2. ...

  4. JNI查找 native 方法的规则(静态、动态注册)

    转载自:JNI查找 native 方法的规则 通过上一篇文章,大家明白了调用 native 方法之前,首先要调用 System.loadLibrary 接口加载一个实现了native 方法的动态库才能 ...

  5. Android逆向之旅---抖音短视频的Native注册混淆函数获取方法

    一.静态分析 最近在小密圈中有很多同学都在咨询有时候有些应用的动态注册Native函数,在分析so之后发现找不到真的实现函数功能地方,我们知道有时候为了安全考虑会动态注册Native函数,但是如果只是 ...

  6. Android平台dalvik模式下java Hook框架ddi的分析(1)

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/75710411 一.前 言 在前面的博客中已经学习了作者crmulliner编写的, ...

  7. Android平台的Python-基础篇(一)-详细版

    目录 1. 前言 2. Python与C交互基础 2.1 C调用Python 2.1.1 简单使用 2.1.2 C调用Python函数 2.1.3 C调用Python基础API 2.2 Python ...

  8. Android之JNI动态注册native方法和JNI数据简单使用

    1.爆结果照片 2.介绍JNI注册方式 JVM 查找 native 方法有两种方式:     1).按照 JNI 规范的命名规则(静态注册)    2) .调用 JNI 提供的 RegisterNat ...

  9. Android NDK之静态/动态注册Native方法

    一.简介 关于NDK有两种方法注册:静态注册和动态注册. 静态注册: 就是直接在Java文件里写个native方法 然后再c/c++文件中实现这个方法就行了: 动态注册: 就是为了不要写很长的方法名, ...

最新文章

  1. Raspberry Pi, UPNP(二), Scala
  2. 玩转GIT系列之【如何恢复windows系统下git的状态图标显示】
  3. 对产品质量的一点思考
  4. 什么是交换机?交换机的工作原理是什么?
  5. Getting Started with the Table Component
  6. linux--切换ipython解释器到python3
  7. C++11新特性以及std::thread多线程编程
  8. 软件工程的未来发展趋势[转载]
  9. Python 入门,看这篇就够了
  10. 用Python实现ax²+by的图灵机【形式语言与自动机】
  11. 多源最短路(Floyd算法)
  12. BZOJ3757 苹果树
  13. mysql 多表查询 like_MYSQL多表联合查询的问题
  14. 通过自定义函数计算阶乘
  15. 【mysql表查询】某门课程的前三名(包含并列)
  16. 猫和老鼠服务器正在修复中,猫和老鼠手游:关于29日在游戏中出现的异常问题 是暗改还是bug?...
  17. 芯片设计:FPGA开发学习
  18. 浏览器被恶意篡改怎么办?
  19. 【CZY选讲·Triangle】
  20. IOS破解软件,比较全的网站。

热门文章

  1. 445 - Marvelous Mazes
  2. 寻找两个字符串相似度的代码
  3. html-body标签中相关标签 02
  4. windows下nginx+tomcat分布式集群部署
  5. Alamofire 的使用
  6. springmvc + jquery 错误.ClassNotFoundException: org.apache.taglibs.standard.tlv.JstlCoreTLV
  7. Android:字节跳动必备Context原理解析及使用
  8. Android selector
  9. 第四周项目五-用递归方法求解(求1*3*5*...*n的递归式)
  10. 不怕面试再问 Activity,一次彻底地梳理(原理+生命周期)