深入理解JNI---碎碎念2
来源:互联网 发布:奉化房产信息网域名 编辑:程序博客网 时间:2024/05/21 11:12
JNI
Java Native Interface是一种技术,通过这种技术可以实现:
1) java程序中的函数可以调用native语言中的函数;
2) native程序中的函数可以调用java层的函数;
JNI技术根本是如何将java层的函数对应到native层,如何在native层调用java传递的参数。Java层调用native层需要在native层是对该函数进行注册,注册又分为静态注册和动态注册,注册之后在java层中声明的native方法就可以在native层实现。Native层的方法传入的java层的参数,又需要调用参数的方法。
Java层调用:
public class MediaScanner{
static{
/*加载对应的JNI库,media_jni是JNI库的名字。在实际加载中会拓展成libmedia_jni.so,在windows下拓展成media_jni.dll*/
System.loadLibrary("media_jni");// 加载so文件
native_init();//直接调用native
}
private static native final void native_init();
}
如何将native层的方法对应到privatestaticnativefinalvoidnative_init()就是注册的过程;
静态方法注册:
1 先编写java代码,生成.class文件;
2 使用java工具程序javah,javah –o output packagename.classname, 这样就会生成一个output.h的jni层头文件,文件里包括生成对应的jni的函数声明,实现其函数就可以了。(方法名包括java层的报名,将.改为_)
当java层调用native_init函数时,它会从对应的JNI库中寻找Java_android_media_MediaScanner_native_init函数,如果没有就会报错。如果找到,则会为这个native_init和Java_android_media_MediaScanner_native_init建立关联关系,其实就保存JNI层函数的函数指针。
静态注册的弊端
1 需要编译所有声明了native函数的java类,每个所生成的class都用javah生成一个头文件;
2 javah生成的JNI层函数名特别长,书写不变;
3 初次调用native函数时要根据函数搜索对应的JNI层函数来建立关联关系,影响效率;
动态注册:
在jni中有一个JNINativeMethid结构来保存javaNative和jni函数的一一对应关系,其结构体
typedef struct{
// java中Native函数的名字,不用携带包的路径,如”native_init”
const char* name;
// java函数的签名信息,用字符串表示,是参数类型和返回值类型的组合
const char * signature;
void * fnPtr; // JNI层的函数指针,void *类型;
}
AndroidRunTime类提供了一个registerNativeMethods函数完成,registerNativeMethods的实现如下:
IntAndroidRuntime::registerNativeMethods(JNIEnv * env, const char * className,const JNINativeMethod * gMethods, int numMethods)
{
returnjniRegisterNativeMethods(env,className,gMethods,numMethosd);
}
int iniRegisterNativeMethods(JNIEnv * env,const char * className, const JNINativeMethod * gMethods, int numMethods)
{
jclassclazz;
clazz = (*env)->FindClass(env,className);
……
// 调用env的RegisterNatives函数
if((*env)->RegisterNatives(env,clazz,gMethods,numMethods)<0){
return-1;
}
return 0;
}
当Java层通过System.loadLibary加载完成JNI动态库后,紧接着会查找该库中的一个叫JNI_OnLoad的函数。如果有就调用,动态注册的工作就在这里完成。
数据类型转换:
java层到Native的数据类型对应
1 基本数据类型转换:
2 引用数据类型的转换
JNIEnv
JNI_OnLoad的参数JavaVM * vm,void*reserved;调用JavaVM的AttachCurrentThread函数就可以获取这个线程的JNIEnv结构体;在线程退出前需要调用JavaVM的DetachCurrentThread函数来释放对应资源。
通过JNIEnv操作jobject
1 jfieldId和jobject
使用GetFieldId()和GetMethodId()函数获取jfieldID和jmethodID;
使用Call<type>Method()执行函数,静态方法使用CallStatic<type>Method执行函数;type值返回类型。
使用Get<type>Filed() 和Get<type>Field()方法获取和设置jobject的属性值。
参数类型签名的对应
异常处理和垃圾回收……略
- 深入理解JNI---碎碎念2
- android --- 深入理解 JNI
- Android - 深入理解 JNI
- Android - 深入理解 JNI
- 深入理解JNI
- 深入理解JNI
- 深入理解JNI
- android --- 深入理解 JNI
- 深入理解JNI
- 深入理解JNI
- Symbian 碎碎念2
- 碎碎念【2】- 熟能生巧
- 碎碎念2
- 碎碎碎碎念
- JNI——《深入理解(I)》学习笔记2
- 《深入理解Android 卷一》第2章 深入理解JNI
- 碎碎念
- 碎碎念
- 柯南君:教你如何对待大型网站平台的性能优化? 之 二--- 应用程序调优 (长篇总结)
- jquery 表单验证demo
- iOS自动解锁的实现
- Bean-Query 功能改进版(1.1.1)已发布
- 【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试
- 深入理解JNI---碎碎念2
- ASP 的文件操作
- poj解题报告——1845
- mvc中“/”应用程序中的服务器错误。 无法提供此类型的页
- 从bitbucket上clone代码时,遇到:error: Couldn't resolve proxy
- NOJ 1031 建筑群最长坡值 (线性dp)
- stringstream
- 父类的static变量和函数在派生类中依然可用
- android 应用---引导页