2012-12-20 24 views
13

Tôi có một đối tượng java gọi vào đối tượng chia sẻ C++ qua JNI. Trong C++, tôi đang lưu một tham chiếu đến JNIEnv và jObject.Gọi vào đối tượng java đã lưu thông qua JNI từ một chủ đề khác nhau

JavaVM * jvm; 
JNIEnv * myEnv; 
jobject myobj; 

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

Tôi cũng có trình kết xuất GLSurface và cuối cùng nó gọi đối tượng được chia sẻ C++ được đề cập ở trên trên một chủ đề khác, GLThread. Sau đó tôi cố gắng gọi lại vào đối tượng Java ban đầu của tôi bằng cách sử dụng jobject mà tôi đã lưu ban đầu, nhưng Tôi nghĩ rằng vì tôi đang ở trên GLThread, tôi nhận được lỗi sau.

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 

Mã gọi trở lại vào 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); 

}

Nếu thay vào đó tôi tạo ra một jObject mới sử dụng env-> NewObject, tôi succuessfully có thể gọi lại vào Java, nhưng nó là một đối tượng mới và tôi không muốn điều đó. Tôi cần quay lại đối tượng Java ban đầu của mình.

Đây có phải là vấn đề chuyển đổi chuỗi trước khi tôi gọi lại vào Java không? Nếu vậy, làm thế nào để tôi làm như vậy?

Trả lời

24

Truy cập đối tượng từ các chủ đề khác nhau là tốt. Vấn đề là các cuộc gọi JNI nhận các đối tượng như là các tham chiếu cục bộ. Nếu bạn muốn giữ tham chiếu đến jobject giữa JNI cuộc gọi mà bạn cần để làm cho nó tham khảo toàn cầu:

myobj = env->NewGlobalRef(jObj); 

Hãy nhớ để giải phóng nó sau khi bạn sử dụng xong nếu không thì thu gom rác sẽ không thu thập nó và bạn sẽ nhận được rò rỉ bộ nhớ:

myEnv->DeleteGlobalRef(myobj); 

Đọc về tài liệu tham khảo toàn cầu và địa phương here.

+1

đã hoạt động hoàn hảo! –

+0

Xem thêm http://developer.android.com/training/articles/perf-jni.html để biết mẹo này và các mẹo khác. – fadden

+0

Cảm ơn bạn ... Đơn giản và nó hoạt động hoàn hảo –

Các vấn đề liên quan