【问题标题】:How to correctly release memory from JNI?如何从 JNI 中正确释放内存?
【发布时间】:2020-09-26 21:30:30
【问题描述】:

在Java中我称之为矩阵乘法(用于计算方阵的幂):

// Java
public class Matrix {
    // ...
    native void power(double[] a, double[] b, int rows, int cols, int exponent);
    // ...
}

在 C++ 中,这是通过以下方式实现的:

JNIEXPORT void JNICALL power(JNIEnv* env, jobject o,
    jdoubleArray vals, jdoubleArray originalMatrix, jint aRows, jint aCols, jint i) {
            
    jboolean isCopy;

    // Get input array and result array to write values to.
    jdouble* pa = env->GetDoubleArrayElements(vals, &isCopy);
    jdouble* po = env->GetDoubleArrayElements(originalMatrix, &isCopy);

    // Keeping the result of the k-th multiplication.
    jdouble* tmp = new double[aRows * aCols];

    for (int k = 1; k < i; k++) {
        multiply(po, pa, tmp, aRows, aCols, aCols);  // implemented elsewhere (but should be ok)
        memcpy(tmp, pa, aCols * aRows);
    }    
    
    env->ReleaseDoubleArrayElements(vals, pa, 0);    // <- THIS OK?
    env->ReleaseDoubleArrayElements(originalMatrix, po, 0);

    delete[] tmp;
}

【问题讨论】:

    标签: java c++ memory java-native-interface


    【解决方案1】:

    似乎是对的。对于输入数组,您可以在ReleaseDoubleArrayElements 调用中将0 替换为JNI_ABORT,以确保在GetDoubleArrayElements 给您副本的情况下不会进行回写。

    对于输出数组,您还可以考虑使用输入数组的isCopy 结果来确定是否使用SetDoubleArrayRegion 而不是GetDoubleArrayElements/ReleaseDoubleArrayElements。

    【讨论】:

    • JNI_ABORT 究竟是什么意思'
    • 在the JNI documentation中有描述。
    • 我读到的 (对不起,我应该问得更好):“JNI_ABORT: free the buffer without copying back the possible changes 哪个缓冲区是什么意思?而且,如果我想要用 C++ 计算的值,那么我想我想要它们再次使用 Java,那么 JNI_ABORT 对我来说不是错误的选择吗?
    • “哪个缓冲区?” 你从GetDoubleArrayElements 得到的那个。 “如果我想在 C++ 中计算值,那么我想我想再次在 Java 中使用它们” 我的印象是两个数组之一仅用作输入。对于这样的数组,使用JNI_ABORT 是合适的。
    猜你喜欢
    • 2012-04-06
    • 1970-01-01
    • 2020-06-23
    • 2011-06-26
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    相关资源
    最近更新 更多