JNI常用函数说明一

来源:互联网 发布:施耐德m258编程手册 编辑:程序博客网 时间:2024/04/27 13:57

注:本文大部分内容参考http://wenku.baidu.com/link?url=YLs988WKSwRQoV3sOGvhBhH3xALeaSNb17RB4-rQtMIrefRhRIZtBF8bYTAG4Jol0eFBkfjPRBDWikgyLo1bas4xfX4p6YpfexT_GmlWkEK和jni.h,在此基础上添加了一些自己的注释或新增了一些实例。

说明:
1. env参数是指向函数的列表的指针。在C中调用为(*env)->,在C++中调用为(env)->
2. 本地方法的obj 的意义取决于该方法是静态还是实例方法(static or an instance method)。当本地方法作为一个实例方法时,第二个参数相当于对象本身,即this. 当本地方法作为一个静态方法时,
指向所在类。
3. java中的String不管是中文还是英文,一个字符总是对应两个字节
4. Unicode 对应两个字节编码
5. UTF8对应一个字节编码
6. 变量的定义

typedef long jint;typedef __int64 jlong;typedef signed char jbyte;typedef unsigned char   jboolean;typedef unsigned short  jchar;typedef short    jshort;typedef float    jfloat;typedef double   jdouble;typedef jint jsize;

————————–字符系列———————————————————-

1、函数原型:const char* (JNICALL *GetStringUTFChars)(JNIEnv *env, jstring str, jboolean *isCopy)

函数说明:用来取得某个jstring对象相关的Java字符串,把一个Unicode字串转成UTF-8格式字串

参数说明:
jstring str:传入一个指向java中的String对象的jstring变量
jboolean isCopy:传入一个jboolean的指针,是用来标识是否对java的String对象进行了拷贝。如果传入这个jboolean指针不是NULL,则它会给该指针所指向的内存传入JNI_TRUE或JNI_FALSE标识是否进行了拷贝。传入NULL表示不关心是否拷贝字符串,它就不会给jboolean指向的内存赋值。一般会把isCopy设为NULL,不关心Java VM对返回的指针是否直接指向java.lang.String的内容。一般不能预知VM是否会拷贝java.lang.String的内容,程序员应该假设GetStringChars会为java.lang.String分配内存。在JavaVM的实现中,垃圾回收机制会移动对象,并为对象重新配置内存。一旦java.lang.String占用的内存暂时无法被GC重新配置,将产生内存碎片,过多的内存碎片,会更频繁的出现内存不足的假象。
返回类型:char*

2、函数原型: void (JNICALL ReleaseStringUTFChars)(JNIEnv *env, jstring str, const char chars);
函数说明:来释放拷贝的内容
参数说明:
jstring str 指定一个jstring变量,即是要释放的本地字符串的来源
const char* chars 就是要释放的本地字符串

3、函数原型:const jchar *(JNICALL *GetStringChars)(JNIEnv *env, jstring str, jboolean *isCopy);
函数说明:用来取得某个jstring对象相关的Java字符串,以Unicode形式存储
参数说明: 参数和GetStringUTFChars函数参数意思一样
返回类型:jchar 两个字节

4、函数原型:void (JNICALL *Relea

seStringChars)(JNIEnv *env, jstring str, const jchar *chars);

函数说明:同ReleaseStringUTFChars

参数说明: 同ReleaseStringUTFChars

返回类型:void

5、函数原型:jsize (JNICALL *GetStringLength)(JNIEnv *env, jstring str);

函数说明:获得以Unicode编码的字串长度

参数说明: jstring str Java 传进来的字符串对象

返回类型:Java中String对象中字符的个数

6、函数原型: jsize (JNICALL *GetStringUTFLength)(JNIEnv *env, jstring str);

函数说明:获得以UTF8编码的字串长度

参数说明: jstring str Java 传进来的字符串对象

返回类型:Java中String对象中字符的个数

7、函数原型:void GetStringUTFRegion(JNIEnv *env,jstring str, jsize start, jsize len, char *buf)

函数说明:拷贝Java字符串并以UTF-8编码传入buffer。把java字符串的内容直接拷贝到C/C++的字符数组中。

在呼叫这个函数之前必须有一个C/C++分配出来的字符串,然后传入到这个函数中进行字符串的拷贝(此函数不分配内存)

参数说明:jstring str Java 传进来的字符串对象

jsize start Java 传进来的字符串对象复制的起始地址

jsize len 复制的数据长度

char *buf 存放数据的buf

返回类型:void

8、函数原型:void GetStringRegion(JNIEnv env,jstring str, jsize start,jsize len,jchar buffer);

函数说明:拷贝java字符串并以UTF-16编码传入buffer

函数说明:同GetStringUTFRegion

参数说明: 同GetStringUTFRegion

返回类型:void

9、函数原型:jstring NewString(JNIEnv env,const jchar str,jsize len);

函数说明:在C/C++本地代码中创建JAVA的String字符串对象

参数说明:const jchar* str 在C中创建的jstring对象

jsize len 组建字符的长度值,从0开始组建

返回类型:jstring

10、函数原型:jstring NewStringUTF(const char * str);

函数说明:在C/C++本地代码中创建JAVA的String字符串对象

参数说明:const char* str 在C中创建的jstring对象

jsize len 组建字符的长度值,从0开始组建

返回类型:jstring

以上函数所用实例:

C语言实现:

JNIEXPORT jstring JNICALL Java_com_tz_test_NativeTest_getCountFromC(JNIEnv * env , jclass obj,jstring str){        //相当于把str转为两字节的Unicode编码        const jchar* getStr = (*env)->GetStringChars(env,str,NULL);        LOGI("getStrData==%s",getStr);        jsize strSize = (*env)->GetStringLength(env,str);        LOGI("getStrData==%d",strSize);        //ReleaseStringChars告诉JVM这个Chars字符串即getCStr不会被使用了,因为getCStr占用的内存会被回收。         (*env)->ReleaseStringChars(env,str,getStr);        //相当于把str转为单字节的UTF编码        const char *getCStr = (*env)->GetStringUTFChars(env,str,NULL);        LOGI("getCStrData==%s",getCStr);        jsize strCSize = (*env)->GetStringUTFLength(env,str);        LOGI("getCStrData==%d",strCSize);        //要使用ReleaseStringUTFChars 告诉JVM这个UTF-8字符串即getCStr不会被使用了,因为getCStr占用的内存会被回收。         (*env)->ReleaseStringUTFChars(env,str,getCStr);        //注意:GetStringUTFRegion和GetStringRegion这两个函数由于内部没有分配内存,        //所以JNI没有提供ReleaseStringUTFRegion和ReleaseStringRegion这样的函数        //GetStringUTFRegion这个函数会做越界检查,如果检查发现越界了,会抛出StringIndexOutOfBoundsException异常,        //这个方法与GetStringUTFChars比较相似,不同的是,GetStringUTFRegion内部不分配内存,不会抛出内存溢出异常。        //分别表示获取Unicode和UTF-8编码字符串指定范围内的内容        char outBuf [10] ;        //将JVM中的字符串以utf-8编码拷入C缓冲区,该函数内部不会分配内存空间        (*env)->GetStringUTFRegion(env,str,0,10,outBuf);        LOGI("getOutCStrData==%s",outBuf);        jchar outJBuf [10];        //将JVM中的字符串以Unicode编码拷入C缓冲区,该函数内部不会分配内存空间        (*env)->GetStringRegion(env,str,0,10,outJBuf);        //从getStr中取出5个unicode长度构建成jstring        jstring jstr = (*env)->NewString(env,getStr,5);        //把cjstring构建成jstring        const char * cjstring = "getstringfromC";        jstr = (*env)->NewStringUTF(env,cjstring);        return jstr;}

字符串操作总结:
1、对于小字符串来说,GetStringRegion和GetStringUTFRegion这两对函数是最佳选择,因为缓冲区可以被编译器提前分配,
而且永远不会产生内存溢出的异常。当你需要处理一个字符串的一部分时,使用这对函数也是不错。因为它们提供了一个开
始索引和子字符串的长度值。另外,复制少量字符串的消耗也是非常小的。

2、获取Unicode字符串和长度,使用GetStringChars和GetStringLength函数

3、获取UTF-8字符串的长度,使用GetStringUTFLength函数

4、创建Unicode字符串,使用NewString函数

5、从Java字符串转换成C/C++字符串,使用GetStringUTFChars函数

6、通过GetStringUTFChars、GetStringChars、GetStringCritical获取字符串,这些函数内部会分配内存,必须调用相对应的
ReleaseXXXX函数释放内存

//——————–数组系列—————————————————————————–

1、函数原型:jbyte * (JNICALL *GetByteArrayElements)(JNIEnv *env, jbyteArray array, jboolean *isCopy);

函数说明 将Java中的byte数组转换成JNI中的基本类型,并由该类型的指针指向第一个元素

参数说明:jbyteArray array,Java中的byte数组

jboolean *isCopy 同字符函数的isCopy

返回类型 jbyte *

2、函数原型:void (JNICALL *ReleaseByteArrayElements)(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode)

函数说明:释放分配的jbyte数组

参数说明:jbyteArray array Java中的byte数组

jbyte *elems 由GetByteArrayElements函数分配的空间

jint mode 释放模式 一般给0

3、函数原型:jsize (JNICALL *GetArrayLength)(JNIEnv *env, jarray array);

函数说明:获得数组元素的个数

参数说明:jarray array Java数组的对象

返回类型: jsize 数组元素个数

4、函数原型:void (JNICALL *GetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);

函数说明:将jbyteArray数组拷贝到buf中

参数说明:jbyteArray array 生成的jbyteArray 数组,可以使Java传递的,也可以使jni中自己生成

jsize start jbyteArray数组的起始地址

jsize 要拷贝的数据长度

jbyte buf 待存放数据的 jbyte buf

返回类型 void

5、函数原型:void (JNICALL *SetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);

函数说明:将 buf数组中的值拷贝到jbyteArray数组中

参数说明:jbyteArray array 生成的jbyteArray 数组,可以使Java传递的,也可以使jni中自己生成

jsize start jbyteArray数组的起始地址, 从buf的首地址开始复制

jsize 要拷贝的数据长度

jbyte buf 待存放数据的 jbyte buf

返回类型 void

6、函数原型:jbyteArray (JNICALL *NewByteArray)(JNIEnv *env, jsize len);

函数说明:生成一个jbyteArray型数组(一维数组)

参数说明:jsize len 生成数组的大小

返回类型:jbyteArray 数组

7、还有其它类型生成的一维数组

1> jbooleanArray (JNICALL *NewBooleanArray)(JNIEnv *env, jsize len);

2> jbyteArray (JNICALL *NewByteArray)(JNIEnv *env, jsize len);

3> jcharArray (JNICALL *NewCharArray)(JNIEnv *env, jsize len);

4> jshortArray (JNICALL *NewShortArray)(JNIEnv *env, jsize len);

5> jintArray (JNICALL *NewIntArray)(JNIEnv *env, jsize len);

6> jlongArray (JNICALL *NewLongArray)(JNIEnv *env, jsize len);

7> jfloatArray (JNICALL *NewFloatArray)(JNIEnv *env, jsize len);

8> jdoubleArray (JNICALL *NewDoubleArray)(JNIEnv *env, jsize len);

9> jobjectArray (JNICALL *NewObjectArray)(JNIEnv *env, jsize len, jclass clazz, jobject init);

C++实例:

static int JNICALL com_notioni_uart_manager_TtyNativeControl__sendMsgToTty(JNIEnv *env,jobject clazz,jbyteArray data){//byte[]    LOGW("com_notioni_uart_manager_TtyNativeControl__sendMsgToTty");     //jbyte * arrayBody = env->GetByteArrayElements(data,0); jsize theArrayLengthJ = env->GetArrayLength(data); BYTE * starter = (BYTE *)arrayBody;    if(mTtyfd < 0){       LOGE("mTtyfd open failure ,non't write");       return -1;    }    jbyte* arrayData = (jbyte*)env->GetByteArrayElements(data,0);    jsize arrayLength = env->GetArrayLength(data);    char* byteData = (char*)arrayData;    int len = (int)arrayLength;  //  LOGW("write data len:%d",len);  //  LOGW("write data:%s",byteData);    int re = write(mTtyfd,byteData,len);    if(re == -1){       LOGE("write device error");    }    //释放GetByteArrayElements申请的资源    env->ReleaseByteArrayElements(env, data, arrayData, 0);    return re;}

还有和jbyteArray一样的其它类型的数组,用法一致

jbooleanArray GetBooleanArrayElements

jbyteArray GetByteArrayElements

jcharArray GetCharArrayElements

jshortArray GetShortArrayElements

jintArray GetIntArrayElements

jlongArray GetLongArrayElements

jfloatArray GetFloatArrayElements

jdoubleArray GetDoubleArrayElements

jobjectArray GetObjectArrayElement

0 0