3

我使用 NDK 为 Java 分配大缓冲区:

allocNativeBuffer(JNIEnv* env, jobject cls, jlong size) {
    void* buffer = malloc(size);
    jobject directBuffer = env->NewDirectByteBuffer(buffer, size);
    jobject globalRef = env->NewGlobalRef(directBuffer);
    return globalRef;
}

使用此缓冲区后,我将其释放:

freeNativeBuffer(JNIEnv* env, jobject cls, jobject globalRef) {
    void *buffer = env->GetDirectBufferAddress(globalRef);
    env->DeleteGlobalRef(globalRef);
    free(buffer);
}

在 Android 2.2 上它可以正常工作,但在 Android 4.0.3 上,应用程序在 DeleteGlobalRef 调用期间崩溃。我究竟做错了什么?

4

1 回答 1

1

ICS 中对全局和局部引用的实现进行了彻底检查,旨在改进 Java 端的内存管理。在开发人员指南中找到解释 在开发人员博客中阅读更多内容。

简而言之,您在 JNI 函数中收到的任何内容,包括函数的globalRef参数freeNativeBuffer(),都是本地引用。您可以在 C 代码中创建并保留全局引用,如下所示:

static jobject globalRef;

allocNativeBuffer(JNIEnv* env, jobject cls, jlong size) {
    void* buffer = malloc(size);
    jobject directBuffer = env->NewDirectByteBuffer(buffer, size);
    globalRef = env->NewGlobalRef(directBuffer);
    return directBuffer;
}

freeNativeBuffer(JNIEnv* env, jobject cls, jobject localRef) {
    void *buffer = env->GetDirectBufferAddress(localRef);
    if (buffer == env->GetDirectBufferAddress(globalRef) {
        /* we received the object that we saved */
        env->DeleteGlobalRef(globalRef);
        free(buffer);
    }
}

PS我发现stackoverflow讨论看起来像是你实验的灵感。请参阅解释,首先不需要创建和删除全局引用的答案。

于 2012-10-10T12:58:39.677 回答