【问题标题】:Android NDK JNI array reference table overflowAndroid NDK JNI 数组引用表溢出
【发布时间】:2013-09-23 03:58:30
【问题描述】:

我有两个函数,但出现 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中的那个。但是我找不到错误在哪里。

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

【问题讨论】:

    标签: android android-ndk


    【解决方案1】:

    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);
    

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

    【讨论】:

    • 是的,dstarray 没有发布。可以将 Dalvik 置于一种始终复制数据而不是直接修改数据的模式,这对于查找此类行为会发生变化的情况很有用。参见developer.android.com/training/articles/perf-jni.html(尤其是原始数组部分)
    • 啊,我明白了。你的意思是Get|Set*ArrayRegion() 函数,总是复制元素,对吧?我只是指Get|Release*ArrayElements()。人们通常希望避免像操作这样的函数中的副本,因为没有中止条件。要始终固定内存位置(如普通的、旧的 C 风格分配),可以在 java 端使用java.nio.Buffer,而在本机端使用GetDirectBufferAddress()docs.oracle.com/javase/1.4.2/docs/guide/jni/…
    • 是的,JNI_COMMIT 是一头奇怪的野兽:有了这个标志,Release...() 可以与fflush() 相比,而不是fclose()
    • 非常感谢大家!我用 0 替换了 JNI_ABORT,它现在可以工作了。 JNI_COMMIT 有一个奇怪的行为,我在这里发现了它在 dalvik 实现上的实际工作方式:link(fadden 的建议)。谢谢!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多