JNI在处理基本类型数组和对象数组上面是不同的。对象数组里面是一些指向对象实例或者其它数组的引用。

因为速度的原因,先通过GetXXXArrayElements函数把简单类型的数组转化成本地类型的数组,并返回其数组的指针,然后通过该指针来对拷贝数组进行处理。
对拷贝数组处理完后,通过ReleaseXXXArrayElements函数把修改后的拷贝数组的反射到java数组,

然后释放所有相关的资源。

基本类型数组:

获取数组元素指针的对应关系:
  函数            数组类型
  GetBooleanArrayElements   boolean
   GetByteArrayElements    byte
  GetCharArrayElements     char
  GetShortArrayElements    short
  GetIntArrayElements     int
   GetLongArrayElements    long
  GetFloatArrayElements     float
  GetDoubleArrayElements   double
  
释放数组元素指针的对应关系:
  Function            Array Type
   ReleaseBooleanArrayElements   boolean
   ReleaseByteArrayElements    byte
   ReleaseCharArrayElements    char
   ReleaseShortArrayElements    short
   ReleaseIntArrayElements     int
   ReleaseLongArrayElements    long
   ReleaseFloatArrayElements    float
   ReleaseDoubleArrayElements   double

数组的引用类型是一般是jarray或者jarray的子类型jintArray。就像jstring不是一个C字符串类型一样,jarray也不是一个C数组类型。
所以,不要直接访问 jarray。你必须使用合适的JNI函数来访问基本数组元素:

使用GetIntArrayRegion 函数来把一个 int数组中的所有元素复制到一个C缓冲区中,然后我们在本地代码中通过C缓冲区来访问这些元素。

 JNIEXPORT jint JNICALL  Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint buf[10];
jint i, sum = 0;
(*env)->GetIntArrayRegion(env, arr, 0, 10, buf); for (i = 0; i < 10; i++) {
sum += buf[i];
}
return sum;
}

JNI支持一系列的Get/Release<Type>ArrayElement 函数,这些函数允许本地代码获取一个指向基本类型数组的元素的指针。

 JNIEXPORT jint JNICALL  Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint *carr;
jint i, sum = 0;
carr = (*env)->GetIntArrayElements(env, arr, NULL); //推荐使用
if (carr == NULL) {
return 0; /* exception occurred */
}
for (i=0; i<10; i++) {
sum += carr[i];
}
(*env)->ReleaseIntArrayElements(env, arr, carr, 0);
return sum;
}

如果你想在一个预先分配的C缓冲区和内存之间交换数据,应该使用Get/Set</Type>ArrayRegion系列函数。这些函数会进行越界检查,在需要的时候会有可能抛出ArrayIndexOutOfBoundsException异常。 
对于少量的、固定大小的数组,Get/Set<Type>ArrayRegion是最好的选择,因为C缓冲区可以在Stack(栈)上被很快地分配,而且复制少量数组元素的代价是很小的。这对函数的另外一个优点就是,允许你通过传入一个索引和长度来实现对子字符串的操作。

如果你没有一个预先分配的 C 缓冲区,并且原始数组长度未定,而本地代码又不想在获取数组元素的指针时阻塞的话,使用 Get/ReleasePrimitiveArrayCritical 函数对。就像Get/ReleaseStringCritical函数对一样,这对函数很小心地使用,以避免死锁。

Get/Release<type>ArrayElements 系列函数永远是安全的。JVM 会选择性地返回一个指针,这个指针可能指向原始数据也可能指向原始数据复制。

对象数组:
JNI提供了一个函数对来访问对象数组。GetObjectArrayElement返回数组中指定位置的元素,而SetObjectArrayElement修改数组中指定位置的元素。
与基本类型的数组不同的是,你不能一次得到所有的对象元素或者一次复制多个对象元素。
字符串和数组都是引用类型,你要使用Get/SetObjectArrayElement来访问字符串数组或者数组的数组。

下面的例子调用了一个本地方法来创建一个二维的 int数组,然后打印这个数组的内容:

 class ObjectArrayTest {
private static native int[][] initInt2DArray(int size);
public static void main(String[] args) {
int[][] i2arr = initInt2DArray(3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(" " + i2arr[i][j]);
}
System.out.println();
}
}
static {
System.loadLibrary("ObjectArrayTest");
}
}

静态本地方法 initInt2DArray 创建了一个给定大小的二维数组。执行分配和初始化数组任务的本地方法可以是下面这样子的:

 JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray(JNIEnv *env, jclass cls, int 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; /* out of memory error thrown */
}
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;
}

转自:http://www.cnblogs.com/lijunamneg/archive/2012/12/22/2828922.html

 Java_com_array_arrayTest_arrayUse( JNIEnv* env,jobject thiz,jobjectArray arrayData)
{ jint i,j; int row = (*env)->GetArrayLength(env, arrayData);//获得行数 jarray myarray = ((*env)->GetObjectArrayElement(env, arrayData, )); int col =(*env)->GetArrayLength(env, myarray); //获得列数 jint jniData[row][col]; for (i = ; i < row; i++){ myarray = ((*env)->GetObjectArrayElement(env, arrayData, i)); jint *coldata = (*env)->GetIntArrayElements(env, (jintArray)myarray, ); for (j=; j<col; j++) {
jniData [i] [j] = coldata[j]; //取出JAVA类中arrayData的数据,并赋值给JNI中的数组
} (*env)->ReleaseIntArrayElements(env, (jintArray)myarray, coldata, ); } }

JNI——访问数组的更多相关文章

  1. 2 通过JNI混合使用Java和C++ -----> 访问数组

    关于c和cpp实现native方法的一些注释: 1>  在jni.h中首先定义了C的实现方式,然后用内联函数实现了Cpp的实现方式,如下所示: const char* GetStringUTFC ...

  2. android JNI 一维数组、二维数组的访问与使用

    在JNI中访问JAVA类中的整型.浮点型.字符型的数据比较简单,举一个简单的例子,如下: //得到类名 jclass cls = (*env)->GetObjectClass(env, obj) ...

  3. Android 通过 JNI 访问 Java 字段和方法调用

    在前面的两篇文章中,介绍了 Android 通过 JNI 进行基础类型.字符串和数组的相关操作,并描述了 Java 和 Native 在类型和签名之间的转换关系. 有了之前那些基础,就可以实现 Jav ...

  4. smarty访问数组中的数据,如果是关联数组直接用点.

    $tpl=new Smarty();//新建一个smarty对象,我使用的是Smarty-3.1.6版本 1.设置smarty模板路径$tpl->setTemplateDir():默认情况下是t ...

  5. C---通过指针访问数组

    C语言规定:如果指针变量P已指向数组中的一个元素,则P+1指向同一数组中的下一个元素. 引入指针变量后,就可以用俩种方法来访问数组元素了. 如果p的初值为&a[0],则: P+i 和a+i 就 ...

  6. [Android]通过JNI访问并操作Bitmap的元素,支持RGB565和ARGB8888

    [Android]通过JNI访问并操作Bitmap的元素,支持RGB565和ARGB8888 标签: androidbitmapjni 2014-05-09 20:35 2985人阅读 评论(1) 收 ...

  7. perl访问数组中变量

    数组一个是存储标量值的无序列表变量. 数组变量以 @ 开头.访问数组元素使用 $ + 变量名称 + [索引值] 格式来读取,实例如下: #!/usr/bin/perl @names = (" ...

  8. js添加key为数字的对象,通过类似于通过访问数组的中括号形式访问对象属性

    var obj={};obj[1] = "mm";obj[2]="nn";console.log(obj[1]); 同var obj={};obj[" ...

  9. 008android初级篇之jni中数组的传递

    008android初级篇之jni中数组的传递 jni中在native中数据类型的实际类型 jchar 占两个字节,跟native c中的char(占一个字节)是两个数据类型 jbyte, unsig ...

随机推荐

  1. kafka异常问题汇总

    1.报错:: java.util.concurrent.ExecutionException: org.apache.kafka.common.errors.NotLeaderForPartition ...

  2. 快速入门Sklearn

    主要确定sklearn的基本流程,然后把sklearn当做螺丝刀来用就行了,需要什么查什么. 基本流程 首先我们回顾一下机器学习的基本流程: 特征工程,包括了数据清洗,数据标准版化,特征选取,特征降维 ...

  3. ProxyHandler处理器__代理设置__自定义opener

    ProxyHandler处理器(代理设置) 使用代理IP,这是爬虫/反爬虫的第二大招,通常也是最好用的. 很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正 ...

  4. BZOJ 4557: [JLoi2016]侦察守卫

    题目大意:每个点有一个放置守卫的代价,同时每个点放置守卫能覆盖到的距离都为d,问覆盖所有给定点的代价是多少. 题解: 树形DP f[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上覆盖y层的最 ...

  5. Java-改变Class

    改变一个Class对象的类型 package com.tj; public class MyClass2 { public static void main(String[] args) { Obje ...

  6. 【14】javascript有哪几种数据类型

    javascript有哪几种数据类型 六种基本数据类型 undefined null string boolean number symbol(ES6) 一种引用类型 Object **

  7. 一款基于jQuery的QQ表情插件

    我们在QQ聊天或者发表评论.微博时,会有一个允许加入表情的功能,点击表情按钮,会弹出一系列表情小图片,选中某个表情图片即可发表的丰富的含表情的内容.今天和大家分享一款基于jQuery的QQ表情插件,您 ...

  8. 推荐两个不错的flink项目

    最近flink真是风生水起,但是浪院长看来这不过是阿里错过了创造spark影响力之后,想要在flink领域创建绝对的影响力.但是,不可否认flink在实时领域确实目前来看独树一帜,当然也有它不适合的地 ...

  9. 北京集训TEST13——PA(Goodness)

    题目: Description 桌面上放有 n 张卡牌.对于每张卡牌,一面是绿色的,另一面是红色的.卡牌的每一面都标有一个整数.对于卡牌a和卡牌b,卡牌a对卡牌b的好感度为卡牌a绿色面的数与卡牌b红色 ...

  10. 【loj6191】「美团 CodeM 复赛」配对游戏

    题目 显然期望dp. 简单想法: f[i][j]表示前i个人中向右看并且没有被消除的人数的概率 如果第i+1个人是向右,$f[i+1][j+1]=f[i][j]/2$ 如果第i+1个人是向左,$f[i ...