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的建议)。谢谢