【原创】JNI使用的总结

最近在JNI的项目,由于第一次使用,查了一些资料,现总结如下:

参考资料:

1、http://docs.oracle.com/javase/6/docs/technotes/guides/jni/index.html

2、http://blog.csdn.net/fightspirite/article/details/6859829

3、http://blog.csdn.net/super005/article/details/6387575

4、http://www.cr173.com/html/17867_1.html

5、http://www.cnblogs.com/codc-5117/archive/2012/09/06/2672815.html

6、http://www.cnblogs.com/codc-5117/archive/2012/09/06/2672833.html

7、http://blog.chinaunix.net/uid-23065002-id-3077584.html

8、http://blog.csdn.net/zgyulongfei/article/details/7409441

总结一:关于JNIEnv和JavaVM

native程序中频繁使用JNIEnv*和JavaVM*。而C和C++代码使用JNIEnv*和JavaVM*这两个指针的做法是有区别的,网上大部分代码都使用C++,基本上找不到关于C和C++在这个问题上的详细叙述。

在C中:

使用JNIEnv* env要这样      (*env)->方法名(env,参数列表)

使用JavaVM* vm要这样       (*vm)->方法名(vm,参数列表)

在C++中:

使用JNIEnv* env要这样      env->方法名(参数列表)

使用JavaVM* vm要这样       vm->方法名(参数列表)

上面这二者的区别是,在C中必须先对env和vm间接寻址(得到的内容仍然是一个指针),在调用方法时要将env或vm传入作为第一个参数。C++则直接利用env和vm指针调用其成员。

总结二:"char *"与"java string"的互相转换

1.jstring转换为C风格字符串

char* test = (char*)(*env)->GetStringUTFChars(env,jstring,NULL);

使用完毕后,应调用:

(*env)->ReleaseStringUTFChars(env,jstring, test);

释放资源。

2.C风格字符串转换为jstring

char charStr[50];

jstring jstr;

jstr = env ->NewStringUTF(charStr);

3.C语言中获取的一段char*的buffer传递给Java

在jni中new一个byte数组,然后使用

(*env)->SetByteArrayRegion(env,bytearray, 0, len, buffer)

操作将buffer拷贝到数组中。

这种方式主要是针对buffer中存在“\0”的情况,如果以C风格字符串的方式读入,就会损失“\0”之后的字符。

4.数组操作

数组操作的相关函数列表如下:

JNI函数                    功能

GetArrayLength             返回数组中的元素数

NewObjectArray             创建一个指定长度的原始数据类型数组

GetObjectArrayElement      返回Object数组的元素

SetObjectArrayElement      设置Object数组的元素

GetObjectArrayRegion       将原始数据类型数组中的内容拷贝到预先分配好的内存缓存中

SetObjectArrayRegion       设置缓存中数组的值

ReleaseObjectArrayRegion   释放GetObjectArrayRegion分配的内存

对int,char等基本数据类型的数组操作,将相关Object名称替换为对应基本数据类型名称即为相关函数。

数组操作的方法选择基于使用者的需求而定,如果使用者需要在内存中拷贝数组并对其进行操作那么一般使用GetObjectArrayRegion和SetObjectArrayRegion函数,否则一般使用SetObjectArrayElement和GetObjectArrayElement函数。

写一个简单的例子,分享一下:

http://pan.baidu.com/s/11MThi

总结三:常用的字符串类型处理的函数:

(1)   const char* GetStringUTFChars (jstring string,jboolean* isCopy)

返回指向字符串UTF编码的指针,如果不能创建这个字符数组,返回null。这个指针在调用ReleaseStringUTFChar()函数之前一直有效。 参数:

string Java字符串对象

isCopy 如果进行拷贝,指向以JNI_TRUE填充的jboolean,否则指向以JNI_FALSE填充的jboolean。

(2)   void ReleaseStringUTFChars(jstring str, const char* chars)

通知虚拟机本地代码不再需要通过chars访问Java字符串。

参数:

string Java字符串对象

chars 由GetStringChars返回的指针

(3)   jstring NewStringUTF(const char *utf)

返回一个新的Java字符串并将utf内容拷贝入新串,如果不能创建字符串对象,返回null。通常在反值类型为string型时用到。

参数:

utf UTF编码的字符串指针,对于数值型参数,在C/C++中可直接使用

参数:

array 数组对象

isCopy 如果进行拷贝,指向以JNI_TRUE填充的jboolean,否则指向以JNI_FALSE填充的jboolean。

例如:jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy)

(4)   void ReleaseXxxArrayElements(xxxArray array,xxx *elems, jint mode)

通知虚拟机不再需要从GetXxxArrayElements得到的指针。

参数:

array 数组对象

elems 不再需要的指向数组元素的指针

mode 0=在更新数组元素后释放elems缓冲器

JNI_COMMIT=在更新数组元素后不释放elems缓冲器

JNI_ABORT=不更新数组元素释放elems缓冲器

例如:void ReleaseBooleanArrayElements(jbooleanArray array,jboolean *elems, jint mode)

(5)   xxxArray NewXxxArray(jsize len)

产生一个新的数组,通常在反值类型为数组型时用到。

参数:

len 数组中元素的个数。

例如:jbooleanArray NewBooleanArray(jsize len)

总结九:JNI内存泄露

一:

在c++中new的对象,如果不返回java,必须用release掉,否则内存泄露。包括NewStringUTF,NewObject等。

如果返回java不必release,java会自己回收。

...

jstring jstr = env->NewStringUTF((*p).sess_id);

...

env->DeleteLocalRef( jstr); /* 必须调用,否则泄露 */

...

jobject jobj = env->NewObject(clazz,midInit); /* 有返回,不用管 */

return jobj;

二:

jstring jstr = (jstring)env->CallObjectMethod(authenRequest, mid_authenReq_getSdId_S);

env->GetStringUTFRegion(jstr,0,env->GetStringLength(jstr),authenReq.sd_id);

当jstr是null时,env->GetStringLength(jstr)会出错,导致jvm崩溃

三:

在 JNI 编程时,正确控制 JNI Local Reference 的生命期。

如果需要创建过多的 Local Reference,那么在对被引用的 Java 对象操作结束后,需要调用 JNI function(如 DeleteLocalRef()),及时将 JNI Local Reference 从 Local Ref 表中删除,以避免潜在的内存泄漏。

时间: 2024-10-19 23:59:53

【原创】JNI使用的总结的相关文章

base64编码及JNI实现,代码非原创,只做整理和实现JNI端交互

直接上代码: #include <stdlib.h> #include <stdio.h> #include <getopt.h> #include <string.h> #include "base64.h" extern "C" { //Base64 编码 int Base64Encode(unsigned char *OrgString, unsigned char *Base64String, int OrgS

【转】 Android的NDK开发(1)————Android JNI简介与调用流程

原文网址:http://blog.csdn.net/conowen/article/details/7521340 ******************************************************************************************** * author:[email protected]大钟                                                                      

【转】android JNI

原文网址:http://jinguo.iteye.com/blog/696185 Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C.C++ 和汇编语言)编写的应用程序和库进行交互操作. 1.从如何载入.so档案谈起 由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Byt

Android Studio JNI体验

最近项目中需要调用c/c++的实现,Android是支持JNI的,所以体验了一下JNI的全过程 1. 前期环境准备 (1) 下载NDK,网址是https://developer.android.com/ndk/downloads/index.html, 国内用户需要翻墙. 目前官网上mac版最新的是android-ndk-r10e-darwin-x86_64.bin, 文件比较大,300多M. 下载下来后,解压到相应目录,备用.解压命令如下: ndk$ chmod a+x android-ndk

解决jni调用在Android5.x系统闪退问题

日志信息如下: 08-14 15:48:41.127: A/art(5526): art/runtime/check_jni.cc:70] JNI DETECTED ERROR IN APPLICATION: illegal class name 'xxx.xxx.xxx' 08-14 15:48:41.127: A/art(5526): art/runtime/check_jni.cc:70] (should be of the form 'package/Class', [Lpackage/

android中使用jni对字符串加解密实现分析

android中使用jni对字符串加解密实现分析 最近项目有个需求,就是要对用户的敏感信息进行加密处理,比如用户的账户密码,手机号等私密信息.在java中,就对字符串的加解密我们可以使用AES算法加密字符串,使用它的好处就不必多说了,但我们又知道android的源代码是可以被反编译的,所以使用纯Java方式的AES加密是不安全的,所以想到了使用android中的jni来对字符串加解密处理,它会产生一个.so文件,更重要的是它通过C/C++代码实现,所以安全行比较高,它可以被反编译成机器码,但几乎

Jni :三维数组处理方法 ,以整形三维数组为例 C++实现

本文原创,转载请注明地址:http://www.cnblogs.com/baokang/p/4982846.html 关于Jni的基本使用方法,请参阅:Java 调用 C++ (Java 调用 dll)康哥手把手教你 关于Jni的调试,请参阅:Jni 调试 : eclipse + Vs 联合调试 不废话了,直接上代码 1.java native 接口 /** * 将三维数组src中的每一个元素平方,dst进行输出 * @param src 输入 * @param dst 输出 */ public

Android之——JNI初探

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47405683 这里,我将用一个小例子的形式来帮助大家初探JNI的用法,首先,大家要先搭建好NDK环境,请大家先阅读<Android之--NDK环境搭建>一文. 一.实现 这个小例子实现的功能就是,通过Android中的java代码来调用C代码实现java代码与C代码之间的交互. 1.布局文件 我们首先在布局文件activity_main.xml中,添加一个按钮控件,并给按钮控件

01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码)

1 什么是JNI JNI Java本地开发接口 JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(C/C++) 通过这个协议,java代码就可以调用外部的C/C++代码,外部的C/C++代码也可以调用Java代码. 2 为什么用JNI 1  JNI扩展了java虚拟机的能力,驱动开发(wifi-hotspot)2.3无线热点共享 2  Native code效率高,数学运算,实时渲染的游戏上,音视频处理(极品飞车),opengl,ffmpeg 3  复用代码(文件压缩,人脸识别)