# JNI 编程上手指南之数组访问 站点:答源(https://www.dandroid.cn/) 原文:https://www.dandroid.cn/archives/20402 Canonical:https://www.dandroid.cn/archives/20402 作者:admin 发布日期:2023-09-15 最后更新:2023-09-15 16:43 分类:JNI / 教程 内容类型:post 说明:本页是原文的纯文本镜像,供大模型与检索器完整读取;不含导航、广告、付费框。引用请以上方「原文」链接为准。 ## 正文 1. 引子 JNI 中的数组分为基本类型数组和对象数组,它们的处理方式是不一样的,基本类型数组中的所有元素都是 JNI的基本数据类型,可以直接访问。而对象数组中的所有元素是一个类的实例或其它数组的引用,和字符串操作一样,不能直接访问 Java 传递给 JNI 层的数组,必须选择合适的 JNI 函数来访问和设置 Java 层的数组对象。 2. 数组访问示例 2.1 基本类型数组 Java 层: private native double[] sumAndAverage(int[] numbers); JNI 层: JNIEXPORT jdoubleArray JNICALL Java_HelloJNI_sumAndAverage(JNIEnv *env, jobject obj, jintArray inJNIArray) { //类型转换 jintArray -> jint* jboolean isCopy; jint* inArray = env->GetIntArrayElements(inJNIArray, &isCopy); if (JNI_TRUE == isCopy) { cout << "C 层的数组是 java 层数组的一份拷贝" << endl; } else { cout << "C 层的数组指向 java 层的数组" << endl; } if(nullptr == inArray) return nullptr; //获取到数组长度 jsize length = env->GetArrayLength(inJNIArray); jint sum = 0; for(int i = 0; i < length; ++i) { sum += inArray[i]; } jdouble average = (jdouble)sum / length; //释放数组 env->ReleaseIntArrayElements(inJNIArray, inArray, 0); // release resource //构造返回数据,outArray 是指针类型,需要 free 或者 delete 吗?要的 jdouble outArray[] = {sum, average}; jdoubleArray outJNIArray = env->NewDoubleArray(2); if(NULL == outJNIArray) return NULL; //向 jdoubleArray 写入数据 env->SetDoubleArrayRegion(outJNIArray, 0, 2, outArray); return outJNIArray; } 2.2 引用类型数组 Java 层: public native String[] operateStringArrray(String[] array); JNI 层: JNIEXPORT jobjectArray JNICALL Java_com_xxx_jni_JNIArrayManager_operateStringArrray (JNIEnv * env, jobject object, jobjectArray objectArray_in) { //获取到长度信息 jsize size = env->GetArrayLength(objectArray_in); /*******获取从JNI传过来的String数组数据**********/ for(int i = 0; i < size; i++) { jstring string_in= (jstring)env->GetObjectArrayElement(objectArray_in, i); char *char_in = env->GetStringUTFChars(str, nullptr); } /***********从JNI返回String数组给Java层**************/ jclass clazz = env->FindClass("java/lang/String"); jobjectArray objectArray_out; const int len_out = 5; objectArray_out = env->NewObjectArray(len_out, clazz, NULL); char * char_out[]= { "Hello,", "world!", "JNI", "is", "fun" }; jstring temp_string; for( int i= 0; i < len_out; i++ ) { temp_string = env->NewStringUTF(char_out[i]); env->SetObjectArrayElement(objectArray_out, i, temp_string); } return objectArray_out; } 2.3 二维数组 Java 层: public native int[][] operateTwoIntDimArray(int[][] array_in); JNI 层: JNIEXPORT jobjectArray JNICALL Java_com_xxx_jni_JNIArrayManager_operateTwoIntDimArray(JNIEnv * env, jobject object, jobjectArray objectArray_in) { /********** 解析从Java得到的int型二维数组 **********/ int i, j ; const int row = env->GetArrayLength(objectArray_in);//获取二维数组的行数 jarray array = (jarray)env->GetObjectArrayElement(objectArray_in, 0); const int col = env->GetArrayLength(array);//获取二维数组每行的列数 //根据行数和列数创建int型二维数组 jint intDimArrayIn[row][col]; for(i =0; i < row; i++) { array = (jintArray)env->GetObjectArrayElement(objectArray_in, i); //操作方式一,这种方法会申请natvie memory内存 jint *coldata = env->GetIntArrayElements((jintArray)array, NULL ); for (j=0; jGetIntArrayRegion((jintArray)array, 0, col, (jint*)&intDimArrayIn[i]); env->ReleaseIntArrayElements((jintArray)array, coldata,0 ); } /**************创建一个int型二维数组返回给Java**************/ const int row_out = 2;//行数 const int col_out = 2;//列数 //获取数组的class jclass clazz = env->FindClass("[I");//一维数组的类 //新建object数组,里面是int[] jobjectArray intDimArrayOut = env->NewObjectArray(row_out, clazz, NULL); int tmp_array[row_out][col_out] = {{0,1},{2,3}}; for(i = 0; i< row_out; i ++) { jintArray intArray = env->NewIntArray(col_out); env->SetIntArrayRegion(intArray, 0, col_out, (jint*)&tmp_array[i]); env->SetObjectArrayElement(intDimArrayOut, i, intArray); } return intDimArrayOut; } 3. JNI 字符串处理函数 GetArrayLength jsize (GetArrayLength)(JNIEnv env, jarray array); 返回数组中的元素个数 NewObjectArray jobjectArray NewObjectArray (JNIEnv *env, jsize length, jclass elementClass, jobject initialElement); 构建 JNI 引用类型的数组,它将保存类 elementClass 中的对象。所有元素初始值均设为 initialElement,一般使用 NULL 就好。如果系统内存不足,则抛出 OutOfMemoryError 异常 GetObjectArrayElement和SetObjectArrayElement jobject GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index) 返回 jobjectArray 数组的元素,通常是获取 JNI 引用类型数组元素。如果 index 不是数组中的有效下标,则抛出 ArrayIndexOutOfBoundsException 异常。 void SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobject value) 设置 jobjectArray 数组中 index 下标对象的值。如果 index 不是数组中的有效下标,则会抛出 ArrayIndexOutOfBoundsException 异常。如果 value 的类不是数组元素类的子类,则抛出 ArrayStoreException 异常。 New\Array 函数集 NativeTypeArray NewArray (JNIEnv* env, jsize size) 用于构造 JNI 基本类型数组对象。 在实际应用中把 PrimitiveType 替换为某个实际的基本类型数据类型,然后再将 NativeType 替换成对应的 JNI Native Type 即可,具体的: 函数名 返回类型 NewBooleanArray() jbooleanArray NewByteArray() jbyteArray NewCharArray() jcharArray NewShortArray() jshorArray NewIntArray() jintArray NewLongArray() jlongArray NewFloatArray() jfloatArray NewDoubleArray() jdoubleArray Get/ReleaseArrayElements函数集 NativeType* GetArrayElements(JNIEnv *env, NativeTypeArray array, jboolean *isCopy) 该函数用于将 JNI 数组类型转换为 JNI 基本数据类型数组,在实际使用过程中将 PrimitiveType 替换成某个实际的基本类型元素访问函数,然后再将NativeType替换成对应的 JNI Native Type 即可: 函数名 转换前类型 转换后类型 GetBooleanArrayElements() jbooleanArray jboolean* GetByteArrayElements() jbyteArray jbyte* GetCharArrayElements() jcharArray jchar* GetShortArrayElements() jshortArray jshort* GetIntArrayElements() jintArray jint* GetLongArrayElements() jlongArray jlong* GetFloatArrayElements() jfloatArray jfloat* GetDoubleArrayElements() jdoubleArray jdouble* void ReleaseArrayElements (JNIEnv *env, NativeTypeArray array, NativeType *elems,jint mode); 该函数用于通知 JVM,数组不再使用,可以清理先关内存了。在实际使用过程中将 PrimitiveType 替换成某个实际的基本类型元素访问函数,然后再将 NativeType 替换成对应的 JNI Native Type 即可: 函数名 NativeTypeArray NativeType ReleaseBooleanArrayElements() jbooleanArray jboolean ReleaseByteArrayElements() jbyteArray jbyte ReleaseCharArrayElements() jcharArray jchar ReleaseShortArrayElements() jshortArray jshort ReleaseIntArrayElements() jintArray jint ReleaseLongArrayElements() jlongArray jlong ReleaseFloatArrayElements() jfloatArray jfloat ReleaseDoubleArrayElements() jdoubleArray jdouble Get/Set\ArrayRegion void SetArrayRegion (JNIEnv *env, NativeTypeArray array, jsize start, jsize len, NativeType *buf); 该函数用于将基本类型数组某一区域复制到 JNI 数组类型中。在实际使用过程中将 PrimitiveType 替换成某个实际的基本类型元素访问函数,然后再将 NativeType 替换成对应的 JNI Native Type 即可: 函数名 NativeTypeArray NativeType SetBooleanArrayRegion() jbooleanArray jboolean SetByteArrayRegion() jbyteArray jbyte SetCharArrayRegion() jcharArray jchar SetShortArrayRegion() jshortArray jshort SetIntArrayRegion() jintArray jint SetLongArrayRegion() jlongArray jlong SetFloatArrayRegion() jfloatArray jfloat SetDoubleArrayRegion() jdoubleArray jdouble --- 由 答源 DAN 底座 1.4.1 生成 · 2026-11-13T19:10:16+00:00