0

ネイティブ 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;
    }
}

copyScreen問題なくJavaからこれを呼び出すことができます。爆撃するのは JNI から呼び出されたときだけです。

どちらの行もコピーしなくても、問題なく動作します。

ログ猫はちょうど示しています:

11-15 20:10:49.234: D/GraphicsBuffer(24341): コピー前画面

ネイティブ コードは、メインとは別のスレッドで実行されていることに注意してください。bmpフィールドへのすべてのアクセスを同期しました。しかし、何もせずに新しいビットマップを作成しても、終了します。ビットマップが小さければ問題ありません。

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

動作しますが、JNI から割り当てることができるものに制限はありますか?

4

1 に答える 1

0

私の問題は、Java環境への参照を保持する方法にあると確信しています。

私の古いメインと 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;
  }

新しいメインと getJNIEnv

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();
于 2012-11-16T22:36:26.827 に答える