DeleteGlobalRef在ICS上崩溃

时间:2012-10-09 15:31:16

标签: android crash android-ndk

我使用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调用。我做错了什么?

1 个答案:

答案 0 :(得分:1)

全局和本地引用的实现在ICS中进行了全面改进,旨在改进Java端的内存管理。在developers guide中查找解释。在developers blog中阅读更多内容。

简而言之,无论您在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 discussion看起来像是您实验的灵感。请参阅answer,其中解释了首先无需创建和删除全局引用。