我有兩個函數,我得到一個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 。但我找不到錯誤在哪裏。
請幫忙! 問候, 胡安·伊格納西奧·
是的,那dstarray沒有被釋放。有可能將Dalvik置入一種模式,它總是複製數據而不是直接修改數據,這對於發現行爲會改變的情況很有用。參見http://developer.android.com/training/articles/perf-jni.html(特別是原始數組部分) – fadden
啊,我明白了。你的意思是'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
是,'JNI_COMMIT'是一個奇怪的野獸:有了這個標誌,'Release ...()'可以與'fflush()'而不是'fclose()'進行比較。 –