Quel est le problème avec cet appel à la méthode Java?

J’essaie d’appeler une méthode Java à partir du code. Le code C écoute les Shift Escape , Shift , Ctrl , puis appelle la méthode Java en indiquant la touche enfoncée. Voici les extraits qui jouent un rôle dans ceci.

C Extrait:

 mid = (*env)->GetMethodID(env,cls,"callBack","(Ljava/lang/Ssortingng;)V"); Env = env; if(called) switch(param) { case VK_CONTROL: printf("Control pressed !\n"); (*Env)->CallVoidMethodA(Env,Obj,mid,"11"); // calling the java method break; case VK_SHIFT: printf("Shift pressed !\n"); (*Env)->CallVoidMethodA(Env,Obj,mid,"10"); // calling the java method break; case VK_ESCAPE: printf("Escape pressed !\n"); (*Env)->CallVoidMethodA(Env,Obj,mid,"1B"); // calling the java method break; default: printf("The default case\n"); break; } 

Extrait de Java:

 public void callBack(Ssortingng key) { Ssortingng x = KeyEvent.getKeyText(Integer.parseInt(key, 16)); System.out.println(x); } 

Lorsque j’exécute le programme et que j’appuie sur la touche Escape le Escape s’affiche sur la console:

 Escape pressed ! # # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x5c8b809a, pid=7588, tid=8088 # # JRE version: 7.0 # Java VM: Java HotSpot(TM) Client VM (20.0-b01 mixed mode, sharing windows-x86 ) # Problematic frame: # V [jvm.dll+0x19809a] # # An error report file with more information is saved as: # W:\UnderTest\NetbeansCurrent\KeyLoggerTester\build\classes\hs_err_pid7588.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/webapps/bugreport/crash.jsp # 

Je sais que j’appelle la fonction Java dans le mauvais sens, mais je ne sais pas où je me trompe. À partir de la sortie, cela suffit lorsque j’appuie sur la touche Escape et qu’une erreur inattendue se produit.

Lien vers le fichier journal

MODIFIER:

Après la réponse de mavroprovato, je reçois toujours les mêmes erreurs.

J’ai édité de cette façon:

 (*Env)->CallVoidMethodA(Env,Obj,mid,(*Env)->NewSsortingngUTF(Env,"1B")); 

MODIFIER:

CODE COMPLET version 1

CODE COMPLET version 2

    La JVM se bloque car le JNIEnv utilisé n’est pas valide. Le code pose également d’autres problèmes.

    La documentation Sun JNI fournit de très bonnes informations concernant les threads.

    Voici quelques éléments évidents:

    Créez une fonction JNI_OnLoad dans votre code. Il sera appelé lors du chargement de la bibliothèque. JavaVM ensuite le pointeur JavaVM cache, car il est valide pour tous les threads. Une alternative consiste à appeler (*env)->GetJavaVM dans la fonction initializeJNIVars mais je préfère la première.

    Dans vos initializeJNIVars vous pouvez enregistrer la référence obj en appelant Obj = (*env)->NewGlobalRef(obj) .

    Dans LowLevelKeyboardProc vous devrez obtenir le pointeur env :

    AttachCurrentThread(JavaVM *jvm, JNIEnv &env, NULL);


    modifier

    OK, voici le code que vous devez append pour le faire fonctionner, je l’ai essayé moi-même et cela fonctionne. NB : je n’ai pas analysé ce que votre code est en train de faire, j’ai juste fait quelques corrections pour le faire fonctionner.

    Ajoutez ces variables à vos autres variables globales:

     static JavaVM *javaVM = NULL; static jmethodID callbackMethod = NULL; static jobject callbackObject = NULL; 

    Vous pouvez supprimer vos variables cls , mid , Env et Obj et utiliser les miennes à la place.

    Créez la méthode JNI_OnLoad dans laquelle vous mettez en cache le pointeur JavaVM:

     JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { JNIEnv *env = 0; if ((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4)) { return JNI_ERR; } javaVM = jvm; return JNI_VERSION_1_4; } 

    Modifiez vos initializeJNIVars pour ressembler à ceci:

     void Java_keylogger_TestKeys_initializeJNIVars(JNIEnv *env, jobject obj) { jclass cls = (*env)->GetObjectClass(env,obj); callbackMethod = (*env)->GetMethodID(env, cls, "callBack", "(Ljava/lang/Ssortingng;)V"); callbackObject = (*env)->NewGlobalRef(env, obj); if(cls == NULL || callbackMethod == NULL) { printf("One of them is null \n"); } called = TRUE; } 

    Et enfin, dans votre code LowLoevelKeyboardProc , vous devrez append ce qui suit:

     ... WPARAM param = kbhook->vkCode; JNIEnv *env; jint rs = (*javaVM)->AttachCurrentThread(javaVM, (void**)&env, NULL); if (rs != JNI_OK) { return NULL; // Or something appropriate... } ... case VK_ESCAPE: printf("Escape pressed !\n"); jssortingng message = (*env)->NewSsortingngUTF(env, "1B"); (*env)->CallVoidMethod(env, callbackObject, callbackMethod, message); break; ... 

    Dans votre unregisterWinHook vous devez supprimer la référence globale afin que les objects puissent être convertis au format GC.

     ... (*env)->DeleteGlobalRef(env, callbackObject); 

    Et c’est tout.

    Je crois que vous ne pouvez pas appeler une méthode Java qui prend un paramètre Ssortingng et lui transmet un caractère char* . Vous devez d’ abord appeler NewSsortingngUTF .

    Je pense que cela est dû à la fonctionnalité UAC activée sur votre système d’exploitation. C’était un bogue pour Java 6. Lisez ceci pour une référence ultérieure.

    La raison pour laquelle je dis cela est que l’événement de la clé d’échappement est déclenché correctement et que le problème ne commence que dès que l’appel de la méthode java est terminé.