2011-09-12 8 views
5

Mam problem z JNI, który mam nadzieję, że ktoś może mi pomóc.
Próbuję wywołać konstruktora klasy Java o nazwie LUSOutputJNI z natywnego wątku.
Uszkadza FindClass (...) tej konkretnej klasy.Problemy z wywołaniem metody Java z natywnego wątku przy użyciu JNI (C++)

Oto kod:

LOGE("1"); 
    JNIEnv *env = NULL; 

    LOGE("2"); 
    int res = -1; 
    res = g_vm->AttachCurrentThread(&env, NULL); 

    if(env == NULL) 
    { 
     LOGE("env is NULL, AttachCurrentThread failed");; 
    } 


    if(res >= 0) 
     LOGE("AttachCurrentThread was successful"); 
    jclass clazz = NULL; 
    jmethodID cid; 

    jclass clazzESEngine; 
    jmethodID callbackid; 

    jobject jCoreOut; 
    static jfieldID fid_ActionState = NULL; 
    static jfieldID fid_nSpeed = NULL; 
    static jfieldID fid_nType = NULL; 
    static jfieldID fid_nInProcess = NULL; 
    static jfieldID fid_nX = NULL; 
    static jfieldID fid_nY = NULL; 
    LOGE("3"); 

    static const char* const ECOClassName = "lus/android/sdk/LUSOutputJNI"; 
    //static const char* const ECOClassName = "android/widget/TextView"; 
    clazz = env->FindClass(ECOClassName); 
    if (clazz == NULL) { 
     LOGE("Can't find class LUSOutputJNI"); 

    } 
    else 
     LOGE("lus/android/sdk/LUSOutputJNI was found, YEY!!"); 

    LOGE("4"); 
    cid = env->GetMethodID(clazz,"<init>", "()V"); 
    LOGE("5"); 
    jCoreOut = env->NewObject(clazz, cid); 

    LOGE("6");  

Oto wynik logcat od kiedy to się nie powiedzie:

E/lusCore_JNI(3040): 1 
E/lusCore_JNI(3040): 2 
E/lusCore_JNI(3040): AttachCurrentThread was successful 
E/lusCore_JNI(3040): 3 
E/lusCore_JNI(3040): Can't find class LUSOutputJNI 
E/lusCore_JNI(3040): 4 
W/dalvikvm(3040): JNI WARNING: JNI method called with exception raised 

Obserwacje:

  • uzyskać wynik z DołączCurrentThread, który jest 0, który h oznacza, że ​​ten załącznik się powiódł + wskaźnik env nie jest już NULL.
  • Jestem pewien, że deklaracja nazwy pakietu LUSOutputJNI (potrójnie sprawdziła się ...)
  • Kiedy próbuję uruchomić FindClass (..) z bardziej popularną nazwą klasy, taką jak android/widget/TextView, I uzyskać pozytywny wynik. Jest tam. Znaczenie przyłączenia wątku i zmiennych env jest w porządku. (Czy mogę to założyć?)
  • Kiedy próbuję uruchomić następujący kod z metody JNI, która ma działający wątek JNI, bez problemu odnajduje klasę LUSOutputJNI.

Co robię źle?

pomoc będzie mile widziane :)

Dziękuję za poświęcony czas,

Ita

+0

Wszelkie odniesienia do tej klasy "LUSOutputJNI"? –

+0

@ K-ballo: To prawdopodobnie klasa wewnętrzna. –

+0

@Ita: Czy Twój inicjator statyczny LUSOutputJNI zgłasza wyjątek? Powinieneś wydrukować wyjątek podniesiony. –

Odpowiedz

6

Znaleziono odpowiedź \ obejść tutaj. (Spójrz na najczęściej zadawane pytania: „FindClass nie znaleźliśmy moją klasę” w JNI tips)

I basicaly zapisane globalnego wg potrzebnych obiektów JClass.
Jednakże, aby skompilować kod, musiałem przezwyciężyć pewne złe zmiany JNI między C/JNI i C++/JNI.
W ten sposób uzyskałem pakiet NewGlobalRef do kompilacji i pracy.

jclass localRefCls = env->FindClass(strLUSClassName); 
if (localRefCls == NULL) { 
    LOGE("Can't find class %s",strLUSCoreClassName); 
    return result; 
} 

//cache the EyeSightCore ref as global 
/* Create a global reference */ 
clazzLUSCore = (_jclass*)env->NewGlobalRef(localRefCls); 

/* The local reference is no longer useful */ 
env->DeleteLocalRef(localRefCls); 

/* Is the global reference created successfully? */ 
if (clazzLUSCore == NULL) { 
    LOGE("Error - clazzLUSCore is still null when it is suppose to be global"); 
    return result; /* out of memory exception thrown */ 
} 

Mam nadzieję, że to pomoże każdemu.

+0

Dzięki, pomogło to. Czy naprawdę konieczne jest tutaj usunięcie lokalnego ref? Sądzę, że są one automatycznie usuwane, gdy funkcja zwraca: http://android-developers.blogspot.co.il/2011/11/jni-local-reference-changes-in-ics.html – snowdragon

2

Aby uzyskać nieco więcej informacji na temat co się dzieje źle (będzie logować się do stderr, nie Loge i nie jestem pewien, jak to zmienić) można dodać trochę drukowanie wyjątku - można to zmienić:

//static const char* const ECOClassName = "android/widget/TextView"; 
clazz = env->FindClass(ECOClassName); 
if (clazz == NULL) { 
    LOGE("Can't find class LUSOutputJNI"); 

} 
else 
    LOGE("lus/android/sdk/LUSOutputJNI was found, YEY!!"); 

do tego:

//static const char* const ECOClassName = "android/widget/TextView"; 
    clazz = env->FindClass(ECOClassName); 
    if (clazz == NULL) { 
     LOGE("Can't find class LUSOutputJNI"); 
     jthrowable exc = env->ExceptionOccurred(); 
     if(exc) 
     { 
      env->ExceptionDescribe(); 
      env->ExceptionClear(); 
     }  
    } 
    else 
     LOGE("lus/android/sdk/LUSOutputJNI was found, YEY!!"); 
+1

Wygląda na to, że możesz uzyskać informacje o błędzie za pomocą funkcji toString wewnątrz j-pot, a następnie przekonwertować ją na ciąg znaków C i wstawić to do funkcji 'LOGE', ale może to być przesada w celu debugowania tego. –