我有C App,它调用了一些java功能.我正在使用JNI.一切正常,但仍有一个小问题.在C App中我有一些巨大的数组. Java App也需要这些数据并返回一大堆结果.目前我只是复制数据(你可以查看下面的代码和平).如果我直接从每个指针从Java App访问这些数组会更好.可能吗?我假设没有(因为JVM),但在这种情况下,我必须向我的老板详细解释:)所以,是或否,以及如何或为什么?
jdoubleArray in2 = env->NewDoubleArray(1000);
jdouble *elems2 = (jdouble*)calloc(1000, sizeof(jdouble));
for(int i = 0; i < 1000; i++)
{
elems2[i] = (jdouble)inputArray[i];
}
env->SetDoubleArrayRegion(in2, 0, 1000, elems2);
if(midCD != NULL)
{
jdouble res1 = env->CallStaticDoubleMethod(cls, midCD, in2);
double res1c = res1;
printf("C++.Res1: %f\n", res1c);
}
解决方法:
jdoubleArray in2 = env->NewDoubleArray(1000);
jboolean isCopy;
jdouble *elems2 = env->GetDoubleArrayElements(in2, &isCopy);
for(int i = 0; i < 1000; i++)
{
elems2[i] = (jdouble)inputArray[i];
}
env->ReleaseDoubleArrayElements(in2, elems2, 0);
elems2 = NULL;
如果在调用GetDoubleArrayElements()之后isCopy是JNI_FALSE,则不会进行任何复制.
编辑:重新阅读您的问题后,您可能需要考虑实现Archie’s idea.这取决于您的Java方法如何使用数据.如果Java方法不使用整个数组,或者不是同时使用整个数组,那么Archie的解决方案是使用本机访问器创建C数组的Java类包装器,这可能是一个很好的解决方案.但是,如果Java方法需要所有数据,那么您可能只需要以最快的方式将数据导入VM,GetDoubleArrayElements()提供了该方法.
如果您对C数组的某些元素进行了更改,并希望对Java副本进行相同的更改,那么SetDoubleArrayRegion()就会发挥作用.
EDIT2:我相信Archie指的是:
public class NativeDoubleArrayProxy {
// This is the native `inputArray' pointer.
private long p;
private int length;
private NativeDoubleArrayProxy(long p, int length) {
this.p = p;
this.length = length;
}
public int length() {
return length;
}
public native double getDouble(int index);
public native void getDoubles(int startingIndex, double[] out, int outOffset, int length);
}
确切的细节取决于inputArray的类型(它是一个原始的C风格数组,还是一个std :: vector< double>,还有什么?).但是我的想法是在JNI端构造一个NativeDoubleArrayProxy对象,并将指针强制转换为jlong. getDouble()和getDoubles()的JNI实现实现了从C到Java的复制代码.
当然,您需要非常小心以确保指针保持有效.
标签:java,memory-management,java-native-interface
来源: https://codeday.me/bug/20190625/1286887.html