2012-12-20 7 views
13

JNI aracılığıyla bir C++ paylaşımlı nesneyi çağıran bir java nesnem var. C++ 'da, JNIEnv ve jObject için bir başvuru kaydediyorum.Farklı bir iş parçacığından JNI aracılığıyla kaydedilmiş bir java nesnesinin çağrılması

JavaVM * jvm; 
JNIEnv * myEnv; 
jobject myobj; 

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

Ben de bir GLSurface oluşturucusunu var ve sonunda C++, farklı bir iş parçacığı üzerinde yukarıda belirtilen paylaşılan nesne, GLTHREAD çağırır. Daha sonra başlangıçta kaydettiğim jobject'i kullanarak orijinal Java nesnesine geri dönmeyi deniyorum, ancak Bence Ben GLThread'de olduğum için aşağıdaki hatayı alıyorum.

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 geri çağırma kodu: Ben kate-> NewObject kullanarak yeni jObject oluşturmak yerine ise

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); 

}

, ben succuessfully Java geri çağırabilir, ama öyle yeni bir nesne ve bunu istemiyorum. Orijinal Java Nesneme geri dönmem gerek.

Java'ya geri dönmeden önce iş parçacıklarının değiştirilmesi meselesi mi? Eğer öyleyse, nasıl yaparım?

cevap

24

Nesneye farklı konulardan erişilmesi sorun değil. Sorun, JNI çağrılarının yerel referanslar olarak nesne almasıdır. Eğer JNI'yı bunu küresel başvuru yapmak gerekir çağrıları arasında jobject başvurusunu tutmak isterseniz:

myobj = env->NewGlobalRef(jObj); 

bunu başka türlü çöp toplayıcı bunu toplamaz kullanılarak bittikten sonra bunu serbest unutmayın ve alacağınız bellek sızıntıları: yerel referanslar vs küresel yaklaşık

myEnv->DeleteGlobalRef(myobj); 

Oku here.

+1

mükemmel çalıştı! –

+0

Ayrıca bu ve diğer ipuçları için http://developer.android.com/training/articles/perf-jni.html adresine bakın. – fadden

+0

Teşekkür ederim ... Basit ve Mükemmel çalışıyor –

İlgili konular