在android中使用NewGlobalReference无效的JNI引用

时间:2012-10-05 09:08:53

标签: java c android-ndk java-native-interface

由于android应用程序内存堆有限,我试图使用malloc和memcpy在C语言中使用位图缓存数组创建。

所以在java方面我有:

private static native Bitmap getJNIBitmap(int id);
private static native void setJNIBitmap(int id, Bitmap bmp);

将位图发送到C:

Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
setJNIBitmap(id, bmp);

从C:

中检索它
Bitmap bitmap = getJNIBitmap(id);

在C代码中,我有一个数组,我想使用位图缓存:

jobject bitmap_array[100];

要在C中保存位图,请使用:

JNIEXPORT void JNICALL Java_droid_demo_ReadingActivity_setJNIBitmap(JNIEnv* env, jobject obj, jint id, jobject jniBmp) {

  AndroidBitmapInfo info;
  AndroidBitmap_getInfo(env, jniBmp, &info);

  long byteSize = (info.stride * info.height)+16;

  bitmap_array[(int)id] = (jobject *)malloc(byteSize);
  memcpy(bitmap_array[(int)id], jniBmp, byteSize);
  (*env)->NewGlobalRef(env, bitmap_array[(int)id]);
}

从C:

中检索位图
JNIEXPORT jobject JNICALL Java_droid_demo_ReadingActivity_getJNIBitmap(JNIEnv * env, jobject obj, jint id) {

  jobject temp = bitmap_array[(int)id];

  return temp;
}

我很擅长使用JNI和C,但在我看来这应该有效。嗯,它没有,我收到:

10-05 10:35:54.890: W/dalvikvm(12493): JNI WARNING: 0x5d5e0008 is not a valid JNI reference
10-05 10:35:54.890: W/dalvikvm(12493):              in Ldroid/demo/ReadingActivity;.setJNIBitmap:(ILandroid/graphics/Bitmap;)V (NewGlobalRef)
10-05 10:35:54.890: I/dalvikvm(12493): "main" prio=5 tid=1 RUNNABLE
10-05 10:35:54.890: I/dalvikvm(12493):   | group="main" sCount=0 dsCount=0 obj=0x41611568 self=0x416019f8
10-05 10:35:54.890: I/dalvikvm(12493):   | sysTid=12493 nice=0 sched=0/0 cgrp=apps handle=1074710320
10-05 10:35:54.890: I/dalvikvm(12493):   | schedstat=( 7665497000 93442000 221 ) utm=418 stm=348 core=1

关于为什么我不能使bitmap_array [(int)id]成为全局引用的任何想法?甚至可能如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

jobject只看起来像C指针。实际上,它是Java虚拟机内部某些信息的不透明句柄。可以将像素数据从Java位图对象复制到本机C数组,但只能通过特殊的API。也可以使用JNI函数从本机C代码创建Java对象,但不能简单地在两者之间进行转换。

答案 1 :(得分:-1)

尝试从一开始就不是Java引用的全局引用开始甚至没有意义。你没有对NewGlobalRef()的结果做任何事情,这使得调用它毫无意义,但是如果你想从jniBmp中创建一个全局引用,那么将它传递给NewGlobalRef()并存储结果在你的数组中。并且复制作业的内容不会首先复制位图数据。