2012-11-15 20 views
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; 
    } 
} 

我可以從Java調用這個copyScreen沒有問題。只有當JNI調用它時纔會炸彈。

如果我不做任何複製行,它也可以正常工作。

日誌貓只是表明:

11-15 20:10:49.234:d/GraphicsBuffer(24341):之前複製畫面

注意,本機代碼在運行線程主要分離。我已同步所有訪問bmp字段。但即使製作新的位圖也不會導致它退出。如果位圖很小,則可以。

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

工程,那麼是否有一些限制,我可以從JNI分配什麼?

+0

什麼是logcat炸彈輸出? – ArtemStorozhuk

+0

@Astor它什麼也沒有顯示 – weston

+0

位圖將仍然在Java堆中分配。你的意思是炸彈?沒有任何反應,應用程序崩潰,至少必須有一些段錯誤或者其他東西...嘗試讓獨立的應用程序重現錯誤併發布JNI代碼。 – auselen

回答

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都是單線程的,但是運行在與main分開的線程中。這是它如何從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();