public class ObjectArrayTest{ public static native int[][] init2DArray(int size); //声明本地方法 public static void main(String[] args) { int i2arr[][] = init2DArray(3); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { System.out.print(" "+i2arr[i][j]); } System.out.print(" "); } } static{ //System.loadLibrary("helloworld"); // 加载库文件 System.load("/Users/zhaoshun/solibs/libObjectArrayTest.so"); } } /** 原型 * Class: jni_sample_ObjectArrayTest * Method: init2SArray * Signature: (I)[[I * JNIEXPORT jobjectArray JNICALL Java_jni_sample_ObjectArrayTest_init2DArray(JNIEnv *, jclass, jint); 输出结果: 0 1 2 1 2 3 2 3 4 */
#include <jni.h> #include <stdio.h> #include "jni_sample_ObjectArrayTest.h" // printf 在stdio.h头文件中 JNIEXPORT jobjectArray JNICALL Java_jni_sample_ObjectArrayTest_init2DArray(JNIEnv *env, jclass cls, jint size) { jobjectArray result; int i; jclass intArrCls = (*env)->FindClass(env,"[I"); if(intArrCls == NULL){ return NULL; /* exception thrown */ } result = (*env)->NewObjectArray(env,size,intArrCls,NULL); if(result == NULL){ return NULL; /* out of memory error thrown */ } for (i = 0;i<size;i++) { jint tmp[256]; /* make sure it is large enough! */ int j; jintArray iarr = (*env)->NewIntArray(env,size); if(iarr == NULL){ return NULL; } for (j=0;j<size;j++) { tmp[j] = i+j; } (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp); (*env)->SetObjectArrayElement(env, result, i, iarr); (*env)->DeleteLocalRef(env, iarr); } return result; } /** newInt2DArray方法首先调用FindClass获得一个一维int数组. "[I"作为JNI类描述符 等价于Java int[]声明。FindClass当装载类失败,返回NULL(可能是没找到类或内存不足)。 注意 类描述符,也可以叫做"类签名"。签名的作用:为了准确描述一件事物. Java Vm定义 了类签名,方法签名;其中方法签名是为了支持方法重载。 FindClass 返回 NULL 的原因: • 提供了错误的类描述符 • 无法在当前ClassLoader上下文中找到类 解决办法: • 认真检查类描述符是否正确 • 以"/"作为包分隔符,即类描述符的形式为"xxx/xxx/xxx",而非"xxx.xxx.xxx",也 可简单记忆为"/"用在本地形式(或虚拟机)中;"."分隔符,用在 Java(Java Programming Language)环境中;并且类描述符末尾没有".java",如 FindClass("java/lang/String")而非 FindClass("java/lang/String.java") • 构造ClassLoader,并利用Class.forName(String name, boolean initialize, ClassLoader loader)装载类 其中第三个解决办法比较复杂,涉及到 Java 的双亲委派模型,类与对象相容性判定等问 题,将有专门文章阐述。 然后调用 NewObjectArray 分配一个对象数组。注意,"基本类型数组"这是个整体的概念, 它是一个对象。后面我们要填充它。 注意,DeleteLocalRef 是释放局部对象引用。 */