2012-12-20 3 views
13

JNI経由でC++共有オブジェクトを呼び出すJavaオブジェクトがあります。 C++では、JNIEnvとjObjectへの参照を保存しています。別のスレッドからJNI経由で保存されたJavaオブジェクトを呼び出す

JavaVM * jvm; 
JNIEnv * myEnv; 
jobject myobj; 

JNIEXPORT void JNICALL Java_org_api_init 
    (JNIEnv *env, jobject jObj) { 
    myEnv = env; 
    myobj = jObj; 
} 

私はGLSurfaceレンダラも持っており、最終的には上記のC++共有オブジェクトを別のスレッドGLThreadで呼び出します。私は最初に保存したjobjectを使って元のJavaオブジェクトにコールバックしようとしていますが、私はと思っています。私はGLThread上にいるので、次のエラーが発生します。

W/dalvikvm(16101): JNI WARNING: 0x41ded218 is not a valid JNI reference 
I/dalvikvm(16101): "GLThread 981" prio=5 tid=15 RUNNABLE 
I/dalvikvm(16101): | group="main" sCount=0 dsCount=0 obj=0x41d6e220 self=0x5cb11078 
I/dalvikvm(16101): | sysTid=16133 nice=0 sched=0/0 cgrp=apps handle=1555429136 
I/dalvikvm(16101): | schedstat=(0 0 0) utm=42 stm=32 core=1 

バックのJavaへの呼び出しコード:

void setData() 
    { 
     jvm->AttachCurrentThread(&myEnv, 0); 

     jclass javaClass = myEnv->FindClass("com/myapp/myClass"); 
     if(javaClass == NULL){ 
      LOGD("ERROR - cant find class"); 
     } 

     jmethodID method = myEnv->GetMethodID(javaClass, "updateDataModel", "()V"); 
     if(method == NULL){ 
      LOGD("ERROR - cant access method"); 
     } 

     // this works, but its a new java object 
     //jobject myobj2 = myEnv->NewObject(javaClass, method); 

     //this is where the crash occurs 
     myEnv->CallVoidMethod(myobj, method, NULL); 

}

代わりに私がenv->のNewObjectを使用して新しいjオブジェクトを作成した場合、私はsuccuessfullyバックのJavaに呼び出すことができますが、それはあります新しいオブジェクトと私はそれを望んでいない。元のJavaオブジェクトに戻る必要があります。

Javaにコールバックする前にスレッドを切り替えるのは問題ですか?もしそうなら、どうしたらいいですか?

答えて

24

異なるスレッドからオブジェクトにアクセスするのは問題ありません。問題は、JNIがローカル参照としてオブジェクトを取得することです。あなたはJNIの間JOBJECTへの参照を保持したい場合は、そのグローバル参照にする必要があり呼び出す:

myobj = env->NewGlobalRef(jObj); 

は、あなたがそれを使用して終わった後、それを解放することを忘れないでくださいそれ以外の場合は、ガベージコレクタはそれを収集することはありません、あなたが買ってあげますメモリリーク:

myEnv->DeleteGlobalRef(myobj); 

グローバルとローカルの参照については、hereを参照してください。

+1

は完全に機能しました。 –

+0

このヒントやその他のヒントについては、http://developer.android.com/training/articles/perf-jni.htmlも参照してください。 – fadden

+0

ありがとうございました...シンプルで完全に動作しています –