Android 进阶之JNI 开发 二 JNI数据类型介绍
JNI数据类型
如果需要使用Jni中定义的标准数据类型需要将jni.h include到源码中。
JNI 提供的数据类型包括两类一类是基本数据类型,一类是引用数据类型:
基本数据类型总共有八种如下所示:
引用类型就比较多了整个继承关系如下所示:
还有一个是与访问类对象成员以及类对象方法有关的jfieldID以及jmethodID,这两个方法将会在介绍类成员调用的部分进行介绍。
关于八种基本数据类型我们先不再这里进行介绍了,我们重点介绍下字符串相关的类型以及数组相关类型调用的方法:
字符串相关方法:
jstring 对应的是Java语言中的strings类型,它和标准C语言下的字符串类型是不一样的,C语言中的字符串使用的是char *,是一个指向字符串的一个指针。所以我们需要在native层代码中使用字符串之前将jstring转换为C语言类型的字符串。JNI 提供了Unicode和UTF-8字符串到C语言字符类型之间的相互转换。GetStringUTFChars 这个方法可以将jstring类型的字符串转换为char * 类型,但是这里需要注意的是我们在调用这个方法进行转换的时候不要忘了对返回值进行判空处理,因为Java虚拟机需要分配内存用于存储UTF字符串。这有可能导致内存分配失败。还需要注意的是我们在使用完这些字符后需要调用ReleaseStringUTFChars来释放之前申请的内存。如果没有及时调用ReleaseStringUTFChars或者调用失败,那么就会导致内存泄漏,这个是很严重的问题。
接下来我们还需要看下GetStringUTFChars的第三个参数:这个是用于表示当前访问的字符串是来自原始字符串的拷贝还是直接指向原始字符串,如果返回的为JNI_TRUE那么表示返回的字符串是来自原始字符串的拷贝,如果返回的是JNI_FALSE那么返回的字符串是直接指向原来的字符串,这种情况下要注意不能去修改返回值,否则原始的字符串内容也将会同时被修改。一般我们在不需要关心Java虚拟机返回的是拷贝还是指向原始位置的指针的时候我们可以传递NULL;
如果我们需要使用将C语言类型的字符串转换为Java类型的字符串,那么需要使用NewStringUTF,如果这个方法中分配内存失败那么将会抛出OutOfMemoryError异常,并且返回NULL。
JNIEXPORT jstring JNICALL |
方法名 | 说明 |
---|---|
GetStringChars/ReleaseStringChars | 获取或者释放一个指向Unicode格式字符串的内容的指针,这种情况下有可能返回字符串的拷贝 |
GetStringUTFChars/ReleaseStringUTFChars | 获取或者释放一个指向UTF格式字符串的内容的指针,这种情况下有可能返回字符串的拷贝 |
GetStringLength | 返回在Unicode string中的字符串个数 |
GetStringUTFLength | 返回在UTF-8 string中的字符串个数 |
NewString | 通过传入的Unicode C string 创建一个java.lang.String对象 |
NewStringUTF | 通过传入的UTF-8 C string 创建一个java.lang.String对象 |
Get/ReleaseStringCritical | 这两个方法一般成对使用,在这两个方法之间的native代码必须不能调用哪些会导致当前线程阻塞或者等待其他运行在Java虚拟机上的线程,这些限制可以避免Java虚拟机在native代码持有一个通过GetStringCritical返回的直接指针的时候进行垃圾回收 |
GetStringUTFRegion/SetStringRegion | 由于GetStringUTFRegion没有进行内存分配所以我们不需要进行out-of-memory条件的判断,并且不需要对资源进行释放 |
GetStringUTFRegion/SetStringRegion | 这个与上面的类似 |
下面是关于如何选择对应方法的说明:
数组相关方法:
使用GetIntArrayRegion方法来访问:
JNIEXPORT jint JNICALL |
第三个参数表示起始的index,第四个参数表示需要copy的元素的个数,一旦这些元素都被拷贝到C缓存器那么我们就可以在native层使用这些参数了。同样我们可以使用SetIntArrayRegion方法来设置某个数组的值。对于小型,大小固定的数组Get/Set
使用GetIntArrayElements方法来访问
Java_com_idealist_myapplication_MainActivity_sumOfTheArray(JNIEnv *env, jobject instance, |
GetArrayLength 返回数组中的元素长度
New