Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
2018-01-09 16:48
585 查看
[-]
首先来看一下怎么处理基本类型的数组
在来看一下怎么处理对象型数组
Android应用安全防护和逆向分析
点击立即购买京东 天猫 亚马逊 当当
扫一扫加小编微信添加时请注明编码美丽非常感谢
在Java中数组分为两种:
1.基本类型数组
2.对象类型(Object[])的数组(数组中存放的是指向Java对象中的引用)
一个能通用于两种不同类型数组的函数:
GetArrayLength(jarray array);
(1) Get<Type>ArrayElements(<Type>Array arr , jboolean* isCopide);
这类函数可以把Java基本类型的数组转换到C/C++中的数组,有两种处理方式,一种是拷贝一份传回本地代码,另一个是把指向Java数组的指针直接传回到本地代码中,处理完本地化的数组后,通过Release<Type>ArrayElements来释放数组
(2) Release<Type>ArrayElements(<Type>Array arr , <Type>* array , jint mode)
用这个函数可以选择将如何处理Java跟C++的数组,是提交,还是撤销等,内存释放还是不释放等
mode可以取下面的值:
0 :对Java的数组进行更新并释放C/C++的数组
JNI_COMMIT :对Java的数组进行更新但是不释放C/C++的数组
JNI_ABORT:对Java的数组不进行更新,释放C/C++的数组
(3) GetPrimittiveArrayCritical(jarray arr , jboolean* isCopied);
(4) ReleasePrimitiveArrayCritical(jarray arr , void* array , jint mode);
也是JDK1.2出来的,为了增加直接传回指向Java数组的指针而加入的函数,同样的也会有同GetStringCritical的死锁的问题
(5) Get<Type>ArrayRegion(<Type>Array arr , jsize start , jsize len , <Type>* buffer);
在C/C++预先开辟一段内存,然后把Java基本类型的数组拷贝到这段内存中,这个方法和之前拷贝字符串的GetStringRegion方法的原理是类似的
(6) Set<Type>ArrayRegion(<Type>Array arr , jsize start , jsize len , const <Type>* buffer);
把Java基本类型的数组中的指定范围的元素用C/C++的数组中的元素来赋值
(7) <Type>Array New<Type>Array(jsize sz)
指定一个长度然后返回相应的Java基本类型的数组
JNI没有提供直接把Java的对象类型数组(Object[])直接转到C++中的Object[]数组的函数,而是直接通过Get/SetObjectArrayElement这样的函数来对Java的Object[]数组进行操作由于去的对象数组没有进行拷贝,所以不需要释放任何资源
NewObjectArray可以通过指定长度跟初始值来创建某个类的数组
下面来看一下例子:操作两种类型的数组
Java中的代码:
[java] view
plaincopy
package com.jni.demo;
public class JNIDemo {
//定义一个int型数组
int[] arrays = {4,3,12,56,1,23,45,67};
//定义Father对象数组
Father[] objArrays = {new Father(),new Father(),new Father()};
//定义一个本地方法
public native void callCppFunction();
public static void main(String[] args)throws Exception{
//调用动态链接库
System.loadLibrary("JNIDemo");
JNIDemo jniDemo = new JNIDemo();
jniDemo.callCppFunction();
}
}
</span>
C++中的代码:
[cpp] view
plaincopy
#include<iostream>
#include"com_jni_demo_JNIDemo.h"
#include<algorithm>
using namespace std;
JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_callCppFunction (JNIEnv * env, jobject obj)
{
//获取Java中数组属性arrays的id
jfieldID fid_arrays = env->GetFieldID(env->GetObjectClass(obj),"arrays","[I");
//获取Java中数组属性arrays的对象
jintArray jint_arr = (jintArray)env->GetObjectField(obj,fid_arrays);
//获取arrays对象的指针
jint* int_arr = env->GetIntArrayElements(jint_arr,NULL);
//获取数组的长度
jsize len = env->GetArrayLength(jint_arr);
//打印数组中的值
cout<<"数组的值为:";
for(int s =0;s<len;s++){
cout<<int_arr[s]<<',';
}
cout<<endl;
//新建一个jintArray对象
jintArray jint_arr_temp = env->NewIntArray(len);
//获取jint_arr_temp对象的指针
jint* int_arr_temp = env->GetIntArrayElements(jint_arr_temp,NULL);
//计数
jint count = 0;
//偶数位存入到int_arr_temp内存中
for(jsize j=0;j<len;j++){
if(j%2==0){
int_arr_temp[count++] = int_arr[j];
}
}
//打印int_arr_temp内存中的数组
cout<<"数组中位置是偶数的值为:";
for(jsize k=0;k<count;k++){
cout<<int_arr_temp[k]<<',';
}
cout<<endl;
//将数组中一段(0-2)数据拷贝到内存中,并且打印出来
jint* buffer = new jint[len];
//获取数组中从0开始长度为3的一段数据值
env->GetIntArrayRegion(jint_arr,0,3,buffer);
cout<<"打印数组中0-3一段值:";
for(int l=0;l<3;l++){
cout<<buffer[l]<<',';
}
cout<<endl;
//将数组中的一段(3-7)设置成一定的值,并且打印出来
jint* buffers = new jint[4];
for(int n=0;n<4;n++){
buffers
= n+1;
}
//将buffers这个数组中值设置到数组从3开始长度是4的值中
env->SetIntArrayRegion(jint_arr,3,4,buffers);
//从新获取数组指针
int_arr = env->GetIntArrayElements(jint_arr,NULL);
cout<<"数组中3-7这段的值变成了:";
for(int m=0;m<len;m++){
cout<<int_arr[m]<<',';
}
cout<<endl;
//调用C++标准库中的排序方法sort(...),传递一个数组的开始指针和结束指针
std::sort(int_arr,int_arr+len);
//迭代打印数组中的元素
cout<<"数组排序后的结果:";
for(jsize i=0;i<len;i++){
cout<<int_arr[i]<<',';
}
cout<<endl;
//释放数组指针
env->ReleaseIntArrayElements(jint_arr,int_arr,JNI_ABORT);
//获取Java中对象Father数组属性的id
jfieldID fid_obj_arrays = env->GetFieldID(env->GetObjectClass(obj),"objArrays","[Lcom/jni/demo/Father;");
//获取Java中对象数组Father属性objArrays的对象
jobjectArray jobj_arr = (jobjectArray)env->GetObjectField(obj,fid_obj_arrays);
//从对象数组中获取索引值为1的对象Father
jobject jobj = env->GetObjectArrayElement(jobj_arr,1);
//获取Father对象的class对象
jclass clazz_father = env->GetObjectClass(jobj);
//获取Father对象中的function方法的id
jmethodID id_father_function = env->GetMethodID(clazz_father,"function","()V");
//调用Father对象中的function方法
env->CallVoidMethod(jobj,id_father_function);
//在本地创建一个大小为10的对象数组,对象的初始化都是jobj,也就是方法的第三个参数
jobjectArray jobj_arr_temp = env->NewObjectArray(10,env->GetObjectClass(jobj),jobj);
//获取本地对象数组中第4个对象
jobject jobj_temp = env->GetObjectArrayElement(jobj_arr_temp,3);
//调用Father对象中的function方法
env->CallVoidMethod(jobj_temp,id_father_function);
}
</span>
在Eclipse编译运行结果如下:
首先来看一下怎么处理基本类型的数组
在来看一下怎么处理对象型数组
Android应用安全防护和逆向分析
点击立即购买京东 天猫 亚马逊 当当
扫一扫加小编微信添加时请注明编码美丽非常感谢
在Java中数组分为两种:
1.基本类型数组
2.对象类型(Object[])的数组(数组中存放的是指向Java对象中的引用)
一个能通用于两种不同类型数组的函数:
GetArrayLength(jarray array);
首先来看一下怎么处理基本类型的数组:
(1) Get<Type>ArrayElements(<Type>Array arr , jboolean* isCopide);这类函数可以把Java基本类型的数组转换到C/C++中的数组,有两种处理方式,一种是拷贝一份传回本地代码,另一个是把指向Java数组的指针直接传回到本地代码中,处理完本地化的数组后,通过Release<Type>ArrayElements来释放数组
(2) Release<Type>ArrayElements(<Type>Array arr , <Type>* array , jint mode)
用这个函数可以选择将如何处理Java跟C++的数组,是提交,还是撤销等,内存释放还是不释放等
mode可以取下面的值:
0 :对Java的数组进行更新并释放C/C++的数组
JNI_COMMIT :对Java的数组进行更新但是不释放C/C++的数组
JNI_ABORT:对Java的数组不进行更新,释放C/C++的数组
(3) GetPrimittiveArrayCritical(jarray arr , jboolean* isCopied);
(4) ReleasePrimitiveArrayCritical(jarray arr , void* array , jint mode);
也是JDK1.2出来的,为了增加直接传回指向Java数组的指针而加入的函数,同样的也会有同GetStringCritical的死锁的问题
(5) Get<Type>ArrayRegion(<Type>Array arr , jsize start , jsize len , <Type>* buffer);
在C/C++预先开辟一段内存,然后把Java基本类型的数组拷贝到这段内存中,这个方法和之前拷贝字符串的GetStringRegion方法的原理是类似的
(6) Set<Type>ArrayRegion(<Type>Array arr , jsize start , jsize len , const <Type>* buffer);
把Java基本类型的数组中的指定范围的元素用C/C++的数组中的元素来赋值
(7) <Type>Array New<Type>Array(jsize sz)
指定一个长度然后返回相应的Java基本类型的数组
在来看一下怎么处理对象型数组
JNI没有提供直接把Java的对象类型数组(Object[])直接转到C++中的Object[]数组的函数,而是直接通过Get/SetObjectArrayElement这样的函数来对Java的Object[]数组进行操作由于去的对象数组没有进行拷贝,所以不需要释放任何资源NewObjectArray可以通过指定长度跟初始值来创建某个类的数组
下面来看一下例子:操作两种类型的数组
Java中的代码:
[java] view
plaincopy
package com.jni.demo;
public class JNIDemo {
//定义一个int型数组
int[] arrays = {4,3,12,56,1,23,45,67};
//定义Father对象数组
Father[] objArrays = {new Father(),new Father(),new Father()};
//定义一个本地方法
public native void callCppFunction();
public static void main(String[] args)throws Exception{
//调用动态链接库
System.loadLibrary("JNIDemo");
JNIDemo jniDemo = new JNIDemo();
jniDemo.callCppFunction();
}
}
</span>
C++中的代码:
[cpp] view
plaincopy
#include<iostream>
#include"com_jni_demo_JNIDemo.h"
#include<algorithm>
using namespace std;
JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_callCppFunction (JNIEnv * env, jobject obj)
{
//获取Java中数组属性arrays的id
jfieldID fid_arrays = env->GetFieldID(env->GetObjectClass(obj),"arrays","[I");
//获取Java中数组属性arrays的对象
jintArray jint_arr = (jintArray)env->GetObjectField(obj,fid_arrays);
//获取arrays对象的指针
jint* int_arr = env->GetIntArrayElements(jint_arr,NULL);
//获取数组的长度
jsize len = env->GetArrayLength(jint_arr);
//打印数组中的值
cout<<"数组的值为:";
for(int s =0;s<len;s++){
cout<<int_arr[s]<<',';
}
cout<<endl;
//新建一个jintArray对象
jintArray jint_arr_temp = env->NewIntArray(len);
//获取jint_arr_temp对象的指针
jint* int_arr_temp = env->GetIntArrayElements(jint_arr_temp,NULL);
//计数
jint count = 0;
//偶数位存入到int_arr_temp内存中
for(jsize j=0;j<len;j++){
if(j%2==0){
int_arr_temp[count++] = int_arr[j];
}
}
//打印int_arr_temp内存中的数组
cout<<"数组中位置是偶数的值为:";
for(jsize k=0;k<count;k++){
cout<<int_arr_temp[k]<<',';
}
cout<<endl;
//将数组中一段(0-2)数据拷贝到内存中,并且打印出来
jint* buffer = new jint[len];
//获取数组中从0开始长度为3的一段数据值
env->GetIntArrayRegion(jint_arr,0,3,buffer);
cout<<"打印数组中0-3一段值:";
for(int l=0;l<3;l++){
cout<<buffer[l]<<',';
}
cout<<endl;
//将数组中的一段(3-7)设置成一定的值,并且打印出来
jint* buffers = new jint[4];
for(int n=0;n<4;n++){
buffers
= n+1;
}
//将buffers这个数组中值设置到数组从3开始长度是4的值中
env->SetIntArrayRegion(jint_arr,3,4,buffers);
//从新获取数组指针
int_arr = env->GetIntArrayElements(jint_arr,NULL);
cout<<"数组中3-7这段的值变成了:";
for(int m=0;m<len;m++){
cout<<int_arr[m]<<',';
}
cout<<endl;
//调用C++标准库中的排序方法sort(...),传递一个数组的开始指针和结束指针
std::sort(int_arr,int_arr+len);
//迭代打印数组中的元素
cout<<"数组排序后的结果:";
for(jsize i=0;i<len;i++){
cout<<int_arr[i]<<',';
}
cout<<endl;
//释放数组指针
env->ReleaseIntArrayElements(jint_arr,int_arr,JNI_ABORT);
//获取Java中对象Father数组属性的id
jfieldID fid_obj_arrays = env->GetFieldID(env->GetObjectClass(obj),"objArrays","[Lcom/jni/demo/Father;");
//获取Java中对象数组Father属性objArrays的对象
jobjectArray jobj_arr = (jobjectArray)env->GetObjectField(obj,fid_obj_arrays);
//从对象数组中获取索引值为1的对象Father
jobject jobj = env->GetObjectArrayElement(jobj_arr,1);
//获取Father对象的class对象
jclass clazz_father = env->GetObjectClass(jobj);
//获取Father对象中的function方法的id
jmethodID id_father_function = env->GetMethodID(clazz_father,"function","()V");
//调用Father对象中的function方法
env->CallVoidMethod(jobj,id_father_function);
//在本地创建一个大小为10的对象数组,对象的初始化都是jobj,也就是方法的第三个参数
jobjectArray jobj_arr_temp = env->NewObjectArray(10,env->GetObjectClass(jobj),jobj);
//获取本地对象数组中第4个对象
jobject jobj_temp = env->GetObjectArrayElement(jobj_arr_temp,3);
//调用Father对象中的function方法
env->CallVoidMethod(jobj_temp,id_father_function);
}
</span>
在Eclipse编译运行结果如下:
相关文章推荐
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- JNI--在C/C++中使用java数组
- JNI中如何在本地代码C++中操作java中的基本类型的数组以及对象数组
- Java中JNI的使用详解第六篇:C/C++中的引用类型和Id的缓存
- 2 通过JNI混合使用Java和C++ -----> 访问数组
- 1 通过JNI混合使用Java和C++ -----> 操作字符串
- Android JNI 使用的数据结构JNINativeMethod详解 ||建立Android SDK下的JNI、JAVA应用完整步骤---Android JAVA调用C++代码
- 使用JNI在JAVA和C++之间进行交互操作
- Java中JNI的使用详解第四篇:C/C++中创建Java对象和String字符串对象及对字符串的操作方法
- Java中JNI的使用详解第六篇:C/C++中的引用类型和Id的缓存
- Java中JNI的使用详解第一篇:Jni 调用C++图文教程
- 使用Java操作文本文件的方法详解
- 使用Java操作文本文件的方法详解
- 关于C++调用jar包,在创建虚拟机时使用JNI_CreateJavaVM调用失败返回-1的问题
- 使用JNI进行Java与C/C++语言混合编程(2)--在C/C++中调用Java代码
- android中使用jni 在c++层返回一个数组到java