what is wrong with this call to the java method?

前端 未结 3 1255
鱼传尺愫
鱼传尺愫 2020-12-18 06:57

I am trying to call a Java method from the code. C code listens to either Escape, Shift, Ctrl key press, then it calls the Java method

相关标签:
3条回答
  • 2020-12-18 07:02

    I think it is due to the UAC feature enabled on your Operating System. This was a bug for Java 6. Read this for further reference.

    The reason I say this is because the event to the escape key is fired correctly and the problem only begins as soon as the call to the java method is done.

    0 讨论(0)
  • 2020-12-18 07:08

    I believe you cannot call a java method that takes a String parameter and pass it a char*. You should call NewStringUTF first.

    0 讨论(0)
  • 2020-12-18 07:16

    The JVM is crashing because the JNIEnv that is used is not a valid one. There are other issues with the code as well.

    The Sun JNI documentation is providing very good information regarding threads.

    Here comes some parts that are obvious:

    Create a JNI_OnLoad function in your code. It will be called when the library is loaded. Then cache the JavaVM pointer because that is valid across threads. An alternative is to call (*env)->GetJavaVM in the initializeJNIVars function but I prefer the first one.

    In your initializeJNIVars you can save the obj reference by calling Obj = (*env)->NewGlobalRef(obj).

    In the LowLevelKeyboardProc you will have to get the env pointer:

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


    Edit

    OK, here are the code that you should add to get it working, I have tried it myself and it works. NB: I have not analyzed what your code is actually doing so I just did some fixes to get it working.

    Add these variables among your other global variables:

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

    You can remove your cls, mid, Env and Obj variables and use mine instead.

    Create the JNI_OnLoad method where you cache the JavaVM pointer:

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

    Alter your initializeJNIVars to look like the following:

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

    And finally in your LowLoevelKeyboardProc code you will have to add the following:

    ...
    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");
            jstring message = (*env)->NewStringUTF(env, "1B");
            (*env)->CallVoidMethod(env, callbackObject, callbackMethod, message);
            break;
    ...
    

    In your unregisterWinHook you should delete the global reference so that objects can be GC'd.

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

    And that's it.

    0 讨论(0)
提交回复
热议问题