jni问题摘记
来源:互联网 发布:评标专家库软件 编辑:程序博客网 时间:2024/06/06 09:46
JNI函数的命名规则: Java代码中的函数声明需要添加native 关键 字;Native的对应函数名要以“Java_”开头,后面依次跟上Java的“package名”、“class名”、“函数名”,中间以下划线“_” 分割,在package名中的“.”也要改为“_”。
在JNI的Native函数中,其前两个参数JNIEnv *和jobject 是必需的——前者是一个JNIEnv 结构体的指针,这个结构体中定义了很多JNI的接口函数指针,使开发者可以使用JNI所定义的接口功能;后者指代的是调用这个JNI函数的Java对象,有点类似于C++中的this 指针。
在上述两个参数之后,还需要根据Java端的函数声明依次对应添加参数。
实际上JNI中的局部引用和C语言中局部变量是不同的,他的有效期是当前Native函数被调用的上下文中。我理解的调用上下文,为Java虚拟机的调用流程。Native函数是被Java虚拟机调用的,Native函数执行完成之后,控制流程将继续返回给Java虚拟机。局部变量在Native函数中,由Native代码调用Java虚拟机的JNI接口创建,秉着谁创建谁销毁的原则,当Native函数执行完成之后,如果局部引用没有被Native代码显示删除,那么局部引用在Java虚拟机中还是有效的。Java虚拟机来决定在什么时候来删除这个对象。这和C语言的局部变量概念是不同的。这也可以解释为什么Natvie函数能够以一个局部引用为返回值了。
局部引用在Native代码显示释放非常重要。
(如果你实现的Native函数是工具函数,会被频繁的调用。如果你在Native函数中没有显示删除局部引用,那么每次调用该函数Java虚拟机都会创建一个新的局部引用,造成局部引用过多。尤其是该函数在Native代码中被频繁调用,代码的控制权没有交还给Java虚拟机,所以Java虚拟机根本没有机会释放这些局部变量。)
c和c++的调用是不同的,
*env 和env
另外,折磨了一个下午,实验中不断出问题,搞清楚了,c和c++在编写native函数的时候也是不同的,c函数只要按照规则编写就可可以了。
改成cpp之后,怎么样都调用不了,看到网上不少资料都写到了要生成h文件,以及其中的关键字等等,想想是不是c不同呢,结果换成了c问题解决。
jnI问题
2。 如何将java传入的String参数转换为c的char*,然后使用?
java传入的String参数,在c文件中被jni转换为jstring的数据类型,在c文件中声明char* test,然后test = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);注意:test使用完后,通知虚拟机平台相关代码无需再访问:(*env)->ReleaseStringUTFChars(env, jstring, test);
3. 将c中获取的一个char*的buffer传递给java?
这个char*如果是一般的字符串的话,作为string传回去就可以了。如果是含有’’的buffer,最好作为bytearray传出,因为可以制定copy的length,如果copy到string,可能到’’就截断了。
有两种方式传递得到的数据:
一种是在jni中直接new一个byte数组,然后调用函数(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);将buffer的值copy到bytearray中,函数直接return bytearray就可以了。
一种是return错误号,数据作为参数传出,但是java的基本数据类型是传值,对象是传递的引用,所以将这个需要传出的byte数组用某个类包一下,如下:
class RetObj
{
public byte[] bytearray;
}
这个对象作为函数的参数retobj传出,通过如下函数将retobj中的byte数组赋值便于传出。代码如下:
jclass cls;
jfieldID fid;
jbyteArray bytearray;
bytearray = (*env)->NewByteArray(env,len);
(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);
cls = (*env)->GetObjectClass(env, retobj);
fid = (*env)->GetFieldID(env, cls, "retbytes", "[B"]);
(*env)->SetObjectField(env, retobj, fid, bytearray);
4。 不知道占用多少空间的buffer,如何传递出去呢?
在jni的c文件中new出空间,传递出去。java的数据不初始化,指向传递出去的空间即可。
四.JNI中对JAVA传入数据的处理
1. 如果传入的是bytearray的话,作如下处理得到buffer:
char *tmpdata = (char*)(*env)->GetByteArrayElements(env, bytearray, NULL);
(*env)->ReleaseByteArrayElements(env, bytearray, tmpdata, 0);
五.JAVA调用本地接口后的数据处理问题
1. java得到的数据是String的话,直接处理就可以了。
2. 得到的如果是bytearray的话,作如下处理:
DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytearray));
byte []byte1 = new byte[36];
in.read(byte1,0,36);
String string = new String(byte1);
System.out.println("读出的第一个字段为:"+string);
在JNI的Native函数中,其前两个参数JNIEnv *和jobject 是必需的——前者是一个JNIEnv 结构体的指针,这个结构体中定义了很多JNI的接口函数指针,使开发者可以使用JNI所定义的接口功能;后者指代的是调用这个JNI函数的Java对象,有点类似于C++中的this 指针。
在上述两个参数之后,还需要根据Java端的函数声明依次对应添加参数。
实际上JNI中的局部引用和C语言中局部变量是不同的,他的有效期是当前Native函数被调用的上下文中。我理解的调用上下文,为Java虚拟机的调用流程。Native函数是被Java虚拟机调用的,Native函数执行完成之后,控制流程将继续返回给Java虚拟机。局部变量在Native函数中,由Native代码调用Java虚拟机的JNI接口创建,秉着谁创建谁销毁的原则,当Native函数执行完成之后,如果局部引用没有被Native代码显示删除,那么局部引用在Java虚拟机中还是有效的。Java虚拟机来决定在什么时候来删除这个对象。这和C语言的局部变量概念是不同的。这也可以解释为什么Natvie函数能够以一个局部引用为返回值了。
局部引用在Native代码显示释放非常重要。
(如果你实现的Native函数是工具函数,会被频繁的调用。如果你在Native函数中没有显示删除局部引用,那么每次调用该函数Java虚拟机都会创建一个新的局部引用,造成局部引用过多。尤其是该函数在Native代码中被频繁调用,代码的控制权没有交还给Java虚拟机,所以Java虚拟机根本没有机会释放这些局部变量。)
c和c++的调用是不同的,
*env 和env
另外,折磨了一个下午,实验中不断出问题,搞清楚了,c和c++在编写native函数的时候也是不同的,c函数只要按照规则编写就可可以了。
改成cpp之后,怎么样都调用不了,看到网上不少资料都写到了要生成h文件,以及其中的关键字等等,想想是不是c不同呢,结果换成了c问题解决。
jnI问题
2。 如何将java传入的String参数转换为c的char*,然后使用?
java传入的String参数,在c文件中被jni转换为jstring的数据类型,在c文件中声明char* test,然后test = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);注意:test使用完后,通知虚拟机平台相关代码无需再访问:(*env)->ReleaseStringUTFChars(env, jstring, test);
3. 将c中获取的一个char*的buffer传递给java?
这个char*如果是一般的字符串的话,作为string传回去就可以了。如果是含有’’的buffer,最好作为bytearray传出,因为可以制定copy的length,如果copy到string,可能到’’就截断了。
有两种方式传递得到的数据:
一种是在jni中直接new一个byte数组,然后调用函数(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);将buffer的值copy到bytearray中,函数直接return bytearray就可以了。
一种是return错误号,数据作为参数传出,但是java的基本数据类型是传值,对象是传递的引用,所以将这个需要传出的byte数组用某个类包一下,如下:
class RetObj
{
public byte[] bytearray;
}
这个对象作为函数的参数retobj传出,通过如下函数将retobj中的byte数组赋值便于传出。代码如下:
jclass cls;
jfieldID fid;
jbyteArray bytearray;
bytearray = (*env)->NewByteArray(env,len);
(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);
cls = (*env)->GetObjectClass(env, retobj);
fid = (*env)->GetFieldID(env, cls, "retbytes", "[B"]);
(*env)->SetObjectField(env, retobj, fid, bytearray);
4。 不知道占用多少空间的buffer,如何传递出去呢?
在jni的c文件中new出空间,传递出去。java的数据不初始化,指向传递出去的空间即可。
四.JNI中对JAVA传入数据的处理
1. 如果传入的是bytearray的话,作如下处理得到buffer:
char *tmpdata = (char*)(*env)->GetByteArrayElements(env, bytearray, NULL);
(*env)->ReleaseByteArrayElements(env, bytearray, tmpdata, 0);
五.JAVA调用本地接口后的数据处理问题
1. java得到的数据是String的话,直接处理就可以了。
2. 得到的如果是bytearray的话,作如下处理:
DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytearray));
byte []byte1 = new byte[36];
in.read(byte1,0,36);
String string = new String(byte1);
System.out.println("读出的第一个字段为:"+string);
0 0
- jni问题摘记
- 摘记
- 摘记
- 摘记
- JNI问题
- JNI问题
- JNI问题
- JNI 问题
- Python守护线程被多次运行的问题【摘记】
- 关于SONY笔记本安装Mysql数据库的问题摘记
- 奇怪的JNI问题
- jni使用中的问题
- Java JNI部署问题
- Jni 中文乱码问题
- JNI 编译问题
- Android JNI问题小结
- JNI 遇到的问题
- JNI参数传递问题
- UVA - 568 Just the Facts
- 类成员函数作为多线程的入口函数的实现方法
- Python中用zlib.decompress出错:error: Error -3 while decompressing data: incorrect header check
- hdu 1099
- 网易2011笔试题详解
- jni问题摘记
- 查看CPU信息
- 如何判断手机是否支持OTG
- Android中Animation的使用总结
- OC-内存管理之autorelease和release
- iOS中多任务
- WPF打开文件
- PA的设置,PA功率的设置
- Jxl导出Excel(跨行、设置列宽、设置行高、自动对齐、自定义背景等)