Android NDK JNI数组引用表溢出

时间:2013-09-21 23:33:40

标签: android android-ndk

我有两个函数,我得到一个ReferenceTable溢出。 消耗的数组条目的摘要是:

     1 of byte[] (3 elements)
   446 of byte[] (75 elements) (2 unique instances)
   576 of byte[] (147 elements) (2 unique instances)
     1 of int[] (25 elements)

我真的检查了代码以找出任何错误,但没有找到它。我得到它们后释放数组。唯一的事情是这些函数被调用数千次,这可能是原因吗?

这是我的所有原生代码:

调用一次:

JNIEXPORT void JNICALL Java_ar_com_teasoft_Image_nativeUnlock(
            JNIEnv *env, jclass clazz, jobject bitmap) {
        AndroidBitmap_unlockPixels(env, bitmap);
    }

调用一次:

JNIEXPORT jlong JNICALL Java_ar_com_teasoft_Image_nativeLock(
        JNIEnv *env, jclass clazz, jobject bitmap) {
    int ret;
    AndroidBitmapInfo info;
    if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return 0;
    }
    if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGE("Bitmap format is not RGBA_8888!");
        return 0;
    }
    void* bitmapPixels;
    if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
        return 0;
    }
    return (jlong) bitmapPixels;

}

多次调用:

JNIEXPORT void JNICALL Java_ar_com_teasoft_Image_nativeCopyPixels(
        JNIEnv *env, jclass clazz, jlong dataRef, jintArray sourceIndexes,
        jintArray targetIndexes, jint count) {
    argb* sourcePixels;
    argb* targetPixels;
    jint *sourceArray = env->GetIntArrayElements(sourceIndexes, NULL);
    jint *targetArray = env->GetIntArrayElements(targetIndexes, NULL);
    for (int i = 0; i < count; i++) {
        sourcePixels = (argb*)((char*) dataRef + sourceArray[i] * 4);
        targetPixels = (argb*)((char*) dataRef + targetArray[i] * 4);
        (*targetPixels) = (*sourcePixels);
    }
    env->ReleaseIntArrayElements(sourceIndexes, sourceArray, JNI_ABORT);
    env->ReleaseIntArrayElements(targetIndexes, targetArray, JNI_ABORT);

    }

多次调用:

JNIEXPORT void JNICALL  Java_ar_com_teasoft_Image_nativeGetRGB(
        JNIEnv *env, jclass clazz, jlong dataRef, jintArray indexes,
        jbyteArray destRgb) {
    jint *array = env->GetIntArrayElements(indexes, NULL);
    jbyte *dstarray = env->GetByteArrayElements(destRgb, NULL);
    int size = env->GetArrayLength(indexes);
    char* sourcePixels;
    int dstCount = 0;
    for (int i = 0; i < size; i++) {
        sourcePixels = (char*) dataRef + array[i] * 4;
        dstarray[dstCount++] = (*(sourcePixels + 1));
        dstarray[dstCount++] = (*(sourcePixels + 2));
        dstarray[dstCount++] = (*(sourcePixels + 3));
    }
    env->ReleaseIntArrayElements(indexes, array, JNI_ABORT);
    env->ReleaseByteArrayElements(destRgb, dstarray, JNI_COMMIT);
}

根据摘要,它看起来像是未发布的,是byte [],所以它必须是函数nativeGetRGB中的那个。但我无法找到错误的位置。

请帮忙! 问候, 胡安·伊格纳西奥

1 个答案:

答案 0 :(得分:2)

<强> Java_ar_com_teasoft_Image_nativeGetRGB():

据我所知,您需要通过将0而不是JNI_COMMIT传递给ReleaseByteArrayElements()来提交释放任何临时数组副本。 Get*ArrayElements()的第二个参数是一个指向布尔值的指针,如果返回的数组是副本而不是固定内存,则该指针将设置为true。

<强> Java_ar_com_teasoft_Image_nativeCopyPixels():

您可能还想传递0而不是JNI_ABORT,这会丢弃所有内容,在此处:

env->ReleaseIntArrayElements(targetIndexes, targetArray, JNI_ABORT);

数组的棘手之处在于,释放模式仅适用于复制的数组,因为固定内存会直接修改。没有办法强制阵列复制或固定。