2011-09-12 2 views
5

J'ai un problème JNI auquel j'espère que quelqu'un pourra m'aider.
J'essaye d'appeler un constructeur d'une classe Java appelée LUSOutputJNI à partir d'un thread natif.
Il échoue toujours sur FindClass (...) de cette classe spécifique.Problème d'appel d'une méthode Java à partir d'un thread natif à l'aide de JNI (C++)

Voici le code:

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

est ici la sortie logcat de quand il échoue:

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 

Observations:

  • je reçois un résultat de AttachCurrentThread qui est 0, whic h signifie que cette pièce jointe a réussi + le pointeur env n'est plus NULL.
  • Je suis sûr de la déclaration du nom du paquet de LUSOutputJNI (vérifié ... triple)
  • Lorsque je tente de lancer FindClass (..) avec un nom de classe plus populaires tels que Android/widget/TextView, je obtenir un match positif. C'est là. Ce qui signifie que la connexion de thread et les variables d'environnement sont correctes. (Puis-je supposer que?)
  • Lorsque j'essaie d'exécuter le code suivant à partir d'une méthode JNI qui a un thread JNI qui l'exécute, il trouve la classe LUSOutputJNI sans problème.

Qu'est-ce que je fais mal?

aide sera très appréciée :)

Merci pour votre temps,

Ita

+0

Toute référence à cette classe 'LUSOutputJNI'? –

+0

@ K-ballo: C'est probablement une classe interne. –

+0

@Ita: Votre initialiseur statique LUSOutputJNI lance-t-il une exception? Vous devez imprimer l'exception déclenchée. –

Répondre

6

trouvé la réponse \ contourner ici. (Recherchez la FAQ: "FindClass n'a pas trouvé ma classe" dans JNI tips)

J'ai fondamentalement enregistré une référence globale aux objets jclass nécessaires.
Avait cependant dû surmonter certains changements JNI mal entre C/JNI et C++/JNI afin que le code compiler.
C'est ainsi que j'ai obtenu le NewGlobalRef à compiler et à travailler.

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

J'espère que cela aide tout le monde.

+0

Merci, cela m'a aidé. Est-il vraiment nécessaire de supprimer l'arbitre local ici? Je crois qu'ils sont automatiquement supprimés lorsque la fonction retourne: http://android-developers.blogspot.co.il/2011/11/jni-local-reference-changes-in-ics.html – snowdragon

2

Pour obtenir un peu plus d'informations sur ce qui se passe mal (il stderr, pas LOGE, et Je ne sais pas comment changer cela), vous pouvez ajouter une impression d'exception - vous pouvez modifier ceci:

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

à ceci:

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

On dirait que vous pouvez obtenir l'information d'erreur en utilisant la fonction toString dans jthrowable, puis la convertir en une chaîne C et la mettre dans votre fonction 'LOGE', mais cela peut être exagéré pour le déboguer. –

Questions connexes