2011-09-12 14 views
5

Ho un problema JNI che spero che qualcuno possa aiutarmi con.
Sto provando a chiamare un costruttore di una classe Java chiamata LUSOutputJNI da un thread nativo.
Continua a non riuscire su FindClass (...) di questa classe specifica.Problemi di chiamata su un metodo Java da un thread nativo utilizzando JNI (C++)

Ecco il codice:

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

Ecco l'output logcat da quando non riesce:

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 

Osservazioni:

  • ottengo un risultato da AttachCurrentThread che è 0, che h significa che questo allegato ha avuto successo + il puntatore env non è più NULL.
  • Sono sicuro della dichiarazione del nome del pacchetto di LUSOutputJNI (triplo controllato ...)
  • Quando si tenta di eseguire FindClass (..) con un nome di classe più popolare come Android/widget/TextView, I ottenere una corrispondenza positiva. È qui. Significa che l'allegato al thread e le variabili env sono ok. (Posso supporre che?)
  • Quando si tenta di eseguire il seguente codice da un metodo JNI che ha un thread JNI in esecuzione, trova la classe LUSOutputJNI senza problemi.

Cosa sto sbagliando?

aiuto sarà molto apprezzato :)

Grazie per il vostro tempo,

Ita

+0

Qualsiasi riferimento a questa classe "LUSOutputJNI"? –

+0

@ K-ballo: Probabilmente è una lezione in casa. –

+0

@Ita: l'inizializzatore statico LUSOutputJNI genera un'eccezione? Dovresti stampare l'eccezione sollevata. –

risposta

6

Trovato la risposta \ lavorare qui. (Cerca FAQ: "FindClass non ha trovato la mia classe" in JNI tips)

Ho in pratica salvato un riferimento globale agli oggetti jclass necessari.
Tuttavia, è stato necessario superare alcune modifiche JNI maligne tra C/JNI e C++/JNI per consentire la compilazione del codice.
Ecco come ho ottenuto NewGlobalRef per compilare e lavorare.

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 */ 
} 

Spero che questo aiuti chiunque.

+0

Grazie, questo ha aiutato. È davvero necessario cancellare l'arbitro locale qui? Credo che vengano automaticamente cancellati quando la funzione ritorna: http://android-developers.blogspot.co.il/2011/11/jni-local-reference-changes-in-ics.html – snowdragon

2

Per ottenere un po 'più di informazioni su cosa sta male (si registrerà a stderr, non LOGE, e non sono sicuro di come cambiare che) si può aggiungere un po 'di stampa eccezione - è possibile modificare questa:

//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!!"); 

a tal:

//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

Sembra che tu possa ottenere le informazioni sull'errore usando la funzione toString all'interno del jthrowable, e poi convertirlo in una stringa C e metterlo nella tua funzione 'LOGE', ma questo potrebbe essere eccessivo per il debug di questo. –

Problemi correlati