【JNI探索之路系列】之六:动态库的调用过程
来源:互联网 发布:苹果6s淘宝打字输入法 编辑:程序博客网 时间:2024/06/04 18:04
作者:郭嘉
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
github:https://github.com/AllenWells
【JNI探索之路系列】章节索引
【JNI探索之路系列】之一:JNI简介
【JNI探索之路系列】之二:变量类型
【JNI探索之路系列】之三:JNI方法调用
【JNI探索之路系列】之四:JNI应用接口
【JNI探索之路系列】之五:JNI异常处理
【JNI探索之路系列】之六:动态库的调用过程
一 SO库调用流程
1.1 Java层调用SO库
Java层通过以下两种方式调用SO库。
1 直接调用
System.loadLibrary("ibforlinx_runtime");
这里可以把SO库放在Eclipse下工程的lib/eabi(没有可以新建)目录下,Eclipse可以自动寻找路径。
ibforlinx_runtime.so必须是在java.library.path这一jvm变量所指向的路径中
2 绝对路径
System.load("/system/lib/libforlinx_runtime.so");
这个路径必须是在java.library.path这一jvm变量所指向的路径中,可以通过以下函数获得。
System.getProperty(“java.library.path”);
默认情况下,在Windows平台下,该值包含如下位置:
- 和jre相关的一些目录。
- 程序当前目录。
- Windows目录、
- 系统目录System32
- 系统环境变量path指定目录。
1.2 JNI_OnLoad()被调用
JNI组件被成功加载时,该函数会被回调,JNI_OnLoad()函数主要有两个方面的作用。
1 指定JNI版本,如果未指定,则默认使用1.1.
2 初始化设定,进行各种资源的初始化。
本地方法结构。
typedef struct{ const char* name;// java方法名称 const char* signature; // java方法签名 void* fnPtr;// c/c++的函数指针 } JNINativeMethod;jint JNI_OnLoad(JavaVM* vm, void* reserved){ JNIEnv *env; jvm = vm; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE( "^^^^In JNI_OnLoad(): Failed to get the environment using GetEnv()"); return -1; } //缓存DataExchanger对象 initClassHelper(env, data_exchanger_path, &data_exchanger_obj); //本地函数注册 JNINativeMethod methods[] = { { "setSkbDataToLibrary", "(Lcom/sumavision/bnsas/data/SkbDataFromApk;)I",(void*)Java_com_sumavision_bnsas_data_DataProvider_setSkbDataToLibrary }, { "pushMsgToLibrary", "(I)I",(void *) Java_com_sumavision_bnsas_data_DataProvider_pushMsgToLibrary }, { "getSKBCiferFromLibrary", "()Lcom/sumavision/bnsas/data/SkbCiferData;",(void*)Java_com_sumavision_bnsas_data_DataProvider_getSKBCiferFromLibrary } }; jclass data_exchanger_cls = env->FindClass(data_exchanger_path); // 类、方法数组、方法长度 if (env->RegisterNatives(data_exchanger_cls, methods, sizeof(methods) / sizeof(methods[0]))) { LOGI("^^^^In JNI_OnLoad(): Failed to register native methods"); return -1; } return JNI_VERSION_1_4;}
可以把某些类的对象缓存成全局变量。
void initClassHelper(JNIEnv *env, const char *path, jobject *objptr){ jclass cls = env->FindClass(path); if (NULL == cls) { LOGE("failed to get %s class reference", path); return; } jmethodID constr = env->GetMethodID(cls, "<init>", "()V"); if (NULL == constr) { LOGE("failed to get %s constructor", path); return; } jobject obj = env->NewObject(cls, constr); if (NULL == obj) { LOGE("failed to create a %s object", path); return; } (*objptr) = env->NewGlobalRef(obj);}
当data_exchanger_obj被缓存成全局变量后,就可以通过以下代码来使用data_exchanger_cls里的函数。
JNIEnv *env; jsize nJvms = 0; int status; bool isAttatched = false; if (JNI_GetCreatedJavaVMs(&jvm, 1, &nJvms)) { LOGE("The method JNI_GetCreatedJavaVMs() execute failed\n"); return 7; } status = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_4); if (status < 0) { LOGE("THe method GetEnv() fail to get JNI environment, use ""AttachCurrentThread() to get env"); status = (*jvm)->AttachCurrentThread(jvm, &env, NULL); if (status < 0) { LOGE("The method AttachCurrentThread() fail to attach ""current thread"); return -1; } isAttatched = true; } jclassdata_exchanger_cls=(*env)->GetObjectClass(env,data_exchanger_obj);
1.3 调用SO库中其他业务逻辑
1.4 JNI_OnUnload()被调用
附:
附带说一下JNI的打印调试相关写法:
可以在自己的头文件定义以下宏来进行相关信息的打印。
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)
自己设计了一个打印函数,不过打印的结果有些许问题,待以后验证一下。
int JNILogI(const char *fmt, ...){ int ret = 0; va_list args; va_start(args, fmt); if (JNILogSwitch) { ret = __android_log_print(ANDROID_LOG_INFO, TAG, fmt, args); } va_end(args); fflush(stdout); return ret;}
- 【JNI探索之路系列】之六:动态库的调用过程
- 【JNI探索之路系列】之四:JNI应用接口
- 【JNI探索之路系列】之五:JNI异常处理
- 【JNI探索之路系列】之七:JNI要点总结
- 【JNI探索之路系列】之一:JNI开篇
- 【JNI探索之路系列】之二:变量类型
- Groovy探索之方法调用的动态性
- jni调用DLL动态链接库过程
- android JNI学习之二 调用第三方动态库
- 【媒体应用:Android平台Vitamio播放器探索之路系列】之六:Vitamio API:utils
- 【Java 安全技术探索之路系列:J2SE安全架构】之六:安全管理工具
- 【Android Studio探索之路系列】之六:Android Studio添加依赖
- 【JNI好学易用系列】之三:JNI方法调用
- JNI技术之Java调用C/C++编写的第三方dll-动态链接库
- Android开发艺术探索<Drawable系列之六ClipDrawabe >
- 【Android应用保护技术探索之路系列】之四:对抗动态调试
- android JNI学习之六 JNI的一个框架
- jni的调用过程
- 【JNI探索之路系列】之四:JNI应用接口
- 【JNI探索之路系列】之五:JNI异常处理
- lua中字符串匹配笔记
- 解决360 兼容模式下问题。
- android终端模拟器运行命令可以进行adb connect
- 【JNI探索之路系列】之六:动态库的调用过程
- Linux下使Shell 命令脱离终端在后台运行
- Qt OpenGL----着色、3D和旋转
- POJ 2154 Color (polya 欧拉函数)
- 安全行业,或许很难,但是我来了
- PDF文件怎么才能编辑里面的内容
- Android的AlertDialog详解
- 关于按下shift建后单击选取多个文件
- java大写转化小写的同时小写转化成大写的方法