有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java即使GetPrimitiveArrayCritical失败,我是否应该始终调用ReleasePrimitiveArrayCritical?

我想从JNI代码访问char[],如果可能的话,避免复制。现在,我要做的是:

void my_function(JNIEnv *env, jcharArray array) {
    jsize len = env->GetArrayLength(array);
    if (env->ExceptionCheck() == JNI_TRUE)
        return;

    jchar *chars = env->GetPrimitiveArrayCritical(array);

    // process chars and len

    env->ReleasePrimitiveArrayCritical(array, chars, JNI_ABORT);
}

根据JNI documentationGetPrimitiveArrayCritical可能在“抛出”OOM异常时返回NULL。但是,它们没有明确说明在这种情况下是否仍应调用ReleasePrimitiveArrayCritical

我该怎么办

jchar *chars = env->GetPrimitiveArrayCritical(array);
if (chars == NULL)
    return;

jchar *chars = env->GetPrimitiveArrayCritical(array);
if (chars != NULL) {
    // process chars
}
env->ReleasePrimitiveArrayCritical(array, chars, JNI_ABORT);

共 (3) 个答案

  1. # 1 楼答案

    我对文档的理解是,如果你没有得到你的“chars”,就没有什么可以发布的。通过调用release,您不会释放“数组”,而是释放与数组关联的元素。如有必要,它会释放“字符”(仅当它是副本时)

    如果您是“阵列”的所有者,则需要释放“阵列”。在这种情况下: {code}

    int len = 10;
    jcharArray array = env->NewCharArray(len);
    if (!array) return;
    jchar* chars = env->GetCharArrayElements(array, NULL);
    if (!chars) { env->DeleteLocalRef(array); return; }
    {... do something...}
    env->ReleaseCharArrayElements(array, chars, JNI_ABORT);
    env->DeleteLocalRef(array);
    

    此外,我还发现了这个示例生产代码,它仅在返回的指针不为null时显式调用ReleasePrimitiveArrayCritical

    https://code.google.com/p/chromium/codesearch#chromium/src/third_party/libjpeg_turbo/turbojpeg-jni.c&q=GetPrimitiveArrayCritical&sq=package:chromium&l=365

  2. # 2 楼答案

    查看openjdk code,似乎需要调用ReleasePrimitiveArrayCritical来解锁在GetPrimitiveArrayCritical调用中锁定的GC(GC_locker::unlock_critical

    似乎java数组和本机数组参数也被忽略,而且GetPrimitiveArrayCritical无论如何都不会返回NULL

    但这仅对openjdk 7有效

  3. # 3 楼答案

    ReleasePrimitiveArrayCritical(…, NULL, …)将失败。但我必须承认,我从未经历过GetPrimitiveArrayCritical()返回NULL。遗憾的是,没有办法有条件地请求字节,即没有JNI函数GetPrimitiveArrayCriticalNoCopyOrFail()