在JNI和C中释放持久化数组

时间:2012-08-02 22:03:34

标签: java c java-native-interface

我正在编写一个包装器,以允许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)
}

1 个答案:

答案 0 :(得分:0)

我认为

  1. 正如您所说,您正在制作Java数据的副本,您不需要jlong来获取Java方面的任何内容,而只需将其传递回FreeData
  2. 你不坚持C风格的内存管理,因为你正在使用dereference operator->
  3. 然后有更好的方法来做到这一点,是的。不一定更“有效”(取决于你的意思),但更清晰,更可读。

    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;
    }