Android NDK JNI数组引用表溢出

Android NDK JNI数组引用表溢出,android,android-ndk,Android,Android Ndk,我有两个函数,我得到了一个可引用的溢出。 已使用数组项的摘要为: 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) 我真的检查了代码以发现任何错误,但没有发现。我在获得阵列后释放它们。唯一的问题是这些函数被调用了数千次

我有两个函数,我得到了一个可引用的溢出。 已使用数组项的摘要为:

     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);
}
调用一次:

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);
}
JNIEXPORT jlong JNICALL Java\u ar\u com\u teasoft\u Image\u nativeLock(
JNIEnv*env,jclass clazz,jobject位图){
int ret;
AndroidBitmapInfo信息;
if((ret=AndroidBitmap_getInfo(环境、位图和信息))<0){
LOGE(“AndroidBitmap_getInfo()失败!错误=%d”,ret);
返回0;
}
如果(info.format!=ANDROID\u位图\u格式\u RGBA\u 8888){
LOGE(“位图格式不是RGBA_8888!”);
返回0;
}
void*位图像素;
if((ret=AndroidBitmap_lockPixels(环境、位图和位图像素))<0){
LOGE(“AndroidBitmap_lockPixels()失败!错误=%d”,ret);
返回0;
}
返回(jlong)位图像素;
}
打了很多次电话:

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);
}
JNIEXPORT void JNICALL Java\u ar\u com\u teasoft\u Image\u nativeCopyPixels(
JNIEnv*env、jclass clazz、jlong dataRef、jintArray sourceIndexes、,
金塔瑞目标指数,吉特计数){
argb*源像素;
argb*目标像素;
jint*sourceArray=env->GetIntArrayElements(sourceIndexes,NULL);
jint*targetArray=env->GetIntArrayElements(targetIndex,NULL);
for(int i=0;i发布阵列元素(源索引、源数组、JNI\u中止);
环境->发布安排(目标索引、目标阵列、JNI\u中止);
}
打了很多次电话:

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);
}
JNIEXPORT void JNICALL Java\u ar\u com\u teasoft\u Image\u nativeGetRGB(
JNIEnv*env、jclass clazz、jlong dataRef、jintArray索引、,
jbyteArray(GB){
jint*array=env->GetIntArrayElements(索引,NULL);
jbyte*dstarray=env->GetByteArrayElements(destgb,NULL);
int size=env->GetArrayLength(索引);
字符*源像素;
int-dstCount=0;
对于(int i=0;i释放数组元素(索引、数组、JNI\u中止);
env->ReleaseByteArrayElements(destgb、dstarray、JNI_COMMIT);
}
根据总结,它看起来像是未发布的,是字节[],因此它必须是函数nativeGetRGB中的一个。但是我找不到错误在哪里

请帮忙! 当做
胡安·伊格纳西奥(Juan Ignacio)

Java\u ar\u com\u teasoft\u Image\u nativeGetRGB():

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);
}
据我所知,您需要通过将
0
而不是
JNI\u commit
传递到
ReleaseByteArrayElements()
来提交和释放任何临时数组副本。
Get*ArrayElements()
的第二个参数是指向布尔值的指针,如果返回的数组是副本而不是固定内存,则该参数将设置为true


Java\u ar\u com\u teasoft\u Image\u nativeCopyPixels():

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);
}
您可能还希望传递
0
,而不是
JNI\u ABORT
,这将丢弃所有内容,如下所示:

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

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

是的,该阵列不会被释放。可以将Dalvik置于一种模式,即它总是复制数据,而不是直接修改数据,这对于发现行为会发生变化的情况非常有用。请看(特别是关于基本数组的部分)啊,我明白了。你是说
Get | Set*ArrayRegion()
函数总是复制元素,对吗?我刚才指的是
Get | Release*ArrayElements()
。人们通常希望避免像op那样的函数中的复制,因为没有中止条件。要始终具有固定内存位置(如普通的、旧的C风格的分配),可以在java端使用
java.nio.Buffer
,而在本机端使用
GetDirectBufferAddress()
:是的,
JNI\u COMMIT
是一个奇怪的野兽:有了这个标志,
Release…()
可以与
fflush()相比较
而不是
fclose()
。非常感谢各位!我将JNI_ABORT替换为0,它现在正在工作。JNI_COMMIT有一个奇怪的行为,我在这里发现了它在dalvik实现上的实际工作方式:(fadden的建议)。谢谢