1

我正在编写一个包装器以允许 Java 访问用 C 编写的库。

JNI 调用之间需要有一个持久数组。我在调用之间保留数组地址。这种方法效果很好。我主要担心的是,当数组从 java 复制到 jni 时,JVM 会释放内存,但同时副本会保留在我可以引用的堆上,然后在我完成后释放。

这是两个功能,方法是正确的还是有更有效的方法来做到这一点?

数组导入到 C:

JNIEXPORT jlong JNICALL
Java_Matcher_FlannLoadData(JNIEnv *env, jobject obj, jfloatArray d, jint r, jint c)
{
        int rows = (int)r;
        int cols = (int)c;

        float *jdataset = (*env)->GetFloatArrayElements(env,d,0);

        float *cdataset = malloc(rows*cols*sizeof(float));

        memcpy(cdataset,jdataset,rows*cols*sizeof(float));

        (*env)->ReleaseFloatArrayElements(env,d,jdataset,0);

        return (long)cdataset;
}

空闲内存:

JNIEXPORT void JNICALL
Java_Matcher_FlannFreeData(JNIEnv *env, jobject obj, jlong d)
{
        free((float*)d)
}
4

1 回答 1

0

我假设

  1. 正如您所说,您正在制作 Java 数据的副本,您不需要jlongJava 端的任何东西,您只需将其传回给FreeData
  2. 您不坚持使用 C 风格的内存管理,因为您正在使用取消引用operator->

那么有更好的方法来做到这一点,是的。不一定更“高效”(取决于你的意思),但肯定更干净,更具可读性。

float *cdataset;

JNIEXPORT void JNICALL
Java_Matcher_FlannLoadData(JNIEnv *env, jobject obj, jfloatArray d, jint r, jint c)
{
    ...
    cdataset = new float[rows*cols];
    ...
}

JNIEXPORT void JNICALL
Java_Matcher_FlannFreeData(JNIEnv *env, jobject obj)
{
    delete [] cdataset;
}
于 2012-08-03T15:14:56.470 回答