2013-09-21 101 views
1

我有兩個函數,我得到一個ReferenceTable溢出。 消耗數組項的總結是:Android NDK JNI數組參考表溢出

 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 。但我找不到錯誤在哪裏。

請幫忙! 問候, 胡安·伊格納西奧·

回答

2

Java_ar_com_teasoft_Image_nativeGetRGB():

據我所看到的,你需要通過傳遞0,而不是JNI_COMMITReleaseByteArrayElements()提交沒有任何臨時數組複製。 Get*ArrayElements()的第二個參數是一個指向布爾值的指針,如果返回的數組是一個副本,而不是固定的內存,它將被設置爲true。

Java_ar_com_teasoft_Image_nativeCopyPixels():

您也可能想通過0而不是JNI_ABORT,它丟棄一切,在這裏:

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

與陣列棘手的是,在釋放模式適用僅複製數組,因爲固定內存被直接修改。沒有辦法強制陣列複製或固定。

+1

是的,那dstarray沒有被釋放。有可能將Dalvik置入一種模式,它總是複製數據而不是直接修改數據,這對於發現行爲會改變的情況很有用。參見http://developer.android.com/training/articles/perf-jni.html(特別是原始數組部分) – fadden

+0

啊,我明白了。你的意思是'Get | Set * ArrayRegion()'函數,總是複製元素,對吧?我只是指'Get | Release * ArrayElements()'。一個人通常想避免副本的功能,因爲沒有放棄條件。爲了始終擁有固定的內存位置(如普通的舊C風格分配),可以使用'java.nio。緩衝區「,同時在本機端使用'GetDirectBufferAddress()':http://docs.oracle.com/javase/1.4.2/docs/guide/jni/jni-14.html#GetDirectBufferAddress – Sam

+1

是,'JNI_COMMIT'是一個奇怪的野獸:有了這個標誌,'Release ...()'可以與'fflush()'而不是'fclose()'進行比較。 –

相關問題