Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is wrong with this call to the java method?

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 telling which key was pressed. Following are the snippets that play a role in this.

C Snippet:

mid = (*env)->GetMethodID(env,cls,"callBack","(Ljava/lang/String;)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;
    }

Java Snippet:

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

When I run the program and press the Escape key I get this on the 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
#

I know I am calling the Java function the wrong way, but I don't know where I am wrong. As from the output, it satisfies the case when I press the Escape key and then an unexpected error occurs.

Link to the LOG FILE

EDIT:

After the answer by mavroprovato I still get the same errors.

I edited this way:

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

EDIT:

COMPLETE CODE version 1

COMPLETE CODE version 2

like image 669
Suhail Gupta Avatar asked Jun 05 '12 10:06

Suhail Gupta


People also ask

How do you call a Java method in Java?

Call a MethodInside main , call the myMethod() method: public class Main { static void myMethod() { System.out.println("I just got executed!"); } public static void main(String[] args) { myMethod(); } } // Outputs "I just got executed!"

How does Java method call work?

To call a method in Java, write the method's name followed by two parentheses () and a semicolon; The process of method calling is simple. When a program invokes a method, the program control gets transferred to the called method.

What is calling and called method in Java?

The calling method is the method that contains the actual call. The called method is the method being called.

What happens when you call a method?

When a method is invoked (called), a request is made to perform some action, such as setting a value, printing statements, returning an answer, etc. The code to invoke the method contains the name of the method to be executed and any needed data that the receiving method requires.


2 Answers

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

like image 35
mavroprovato Avatar answered Sep 18 '22 04:09

mavroprovato


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.

like image 119
maba Avatar answered Sep 17 '22 04:09

maba