Android 从本机调用复制位图

Android 从本机调用复制位图,android,android-ndk,java-native-interface,Android,Android Ndk,Java Native Interface,我有一个从本机c代码调用的Java方法。它的工作很简单,复制一个位图。但它使它毫无差错地爆炸了 public synchronized Bitmap copyScreen() { try { Log.d(TAG, "before copy Screen"); //Any of these lines make it bomb out. // Bitmap copy = bmp.copy(bmp.getCo

我有一个从本机c代码调用的Java方法。它的工作很简单,复制一个位图。但它使它毫无差错地爆炸了

public synchronized Bitmap copyScreen() {
    try {
        Log.d(TAG, "before copy Screen");
                          //Any of these lines make it bomb out.
        // Bitmap copy = bmp.copy(bmp.getConfig(), false);
        //Bitmap copy = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(),
        //      bmp.getConfig());
        Bitmap copy = Bitmap.createBitmap(800, 480, Config.ARGB_8888);
        Log.d(TAG, "after copy Screen");
        return copy;
    } catch (Exception ex) {
        Log.e(TAG, "copyScreen", ex);
        return null;
    }
}
我可以毫无问题地从Java调用这个
copyScreen
。只有当它从JNI调用时,它才会爆炸

如果我不做任何复制行,它也可以正常工作

日志只显示:

11-15 20:10:49.234:D/图形缓冲(24341):复制屏幕前

注意,本机代码在与主线程分离的线程中运行。我已同步对
bmp
字段的所有访问。但是,即使制作一个新的位图,也会导致它退出。如果位图很小,就可以了

Bitmap copy = Bitmap.createBitmap(80, 48, Config.ARGB_8888);

工作正常,那么我可以从JNI分配的资源是否有一些限制?

我很确定我的问题在于我对java环境的引用方式:

我的旧main和getJNIEnv

 JNIEnv *_env;

 JNIEXPORT void JNICALL Java_com_comp_prod_main(JNIEnv *env,
        jclass thiz) {
    LOGV("Main called %d", __LINE__);
    _env = (JNIEnv *) ((*env)->NewGlobalRef(env, env));
      main(); //somewhere in here it calls back to the java which creates the bitmap
    _env = NULL;
  }

  JNIEnv *getJNIEnv(void) {
     return _env;
  }
JavaVM *jvm;

JNIEXPORT void JNICALL Java_com_comp_prod_main(JNIEnv *env,
        jclass thiz) {
    LOGV("Main called %d", __LINE__);
    //this is how to cache it for other threads
    jint rs = (*env)->GetJavaVM(env, &jvm);
    assert (rs == JNI_OK);
    main(); //somewhere in here it calls back to the java which creates the bitmap
    jvm = NULL;
}

JNIEnv *getJNIEnv(void) {
    JNIEnv *env;
     jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
     assert (rs == JNI_OK);
     if(env == NULL)
     {
       LOGV("env is NULL");
     }
     return env;
}
我的新main和getJNIEnv

 JNIEnv *_env;

 JNIEXPORT void JNICALL Java_com_comp_prod_main(JNIEnv *env,
        jclass thiz) {
    LOGV("Main called %d", __LINE__);
    _env = (JNIEnv *) ((*env)->NewGlobalRef(env, env));
      main(); //somewhere in here it calls back to the java which creates the bitmap
    _env = NULL;
  }

  JNIEnv *getJNIEnv(void) {
     return _env;
  }
JavaVM *jvm;

JNIEXPORT void JNICALL Java_com_comp_prod_main(JNIEnv *env,
        jclass thiz) {
    LOGV("Main called %d", __LINE__);
    //this is how to cache it for other threads
    jint rs = (*env)->GetJavaVM(env, &jvm);
    assert (rs == JNI_OK);
    main(); //somewhere in here it calls back to the java which creates the bitmap
    jvm = NULL;
}

JNIEnv *getJNIEnv(void) {
    JNIEnv *env;
     jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
     assert (rs == JNI_OK);
     if(env == NULL)
     {
       LOGV("env is NULL");
     }
     return env;
}
仅供参考,所有的c都是单线程的,但是以独立的线程运行到主线程。这是如何从Java开始的:

Runnable runTerm = new Runnable() {

public void run() {
  // call main()
  Log.i(TAG, "About to call main on the c!");
  try {
    Terminal.main();
    } catch (IOException e) {
     e.printStackTrace();
    }
    }
};

t = new Thread(runTerm, "C thread");
t.start();

logcat炸弹输出是什么?位图仍将在Java堆中分配。你说的炸弹是什么意思?什么都没发生,应用程序崩溃,一定是出了什么问题或者至少是出了什么问题。。。尝试制作一个独立的应用程序来重现错误并发布JNI代码。@auselen这是我的想法。日志猫显示Zillch,只是我的日志消息和一般系统的东西。我会尝试制作一个小的复制应用程序。@auselen是的,它是wierd,没有seg故障或任何东西。我想我在解决另一个问题时已经破解了它。