5

コードからJavaメソッドを呼び出そうとしています。Cコードは、キーの押下をリッスンし、Javaメソッドを呼び出して、どのキーが押されたかEscapeを通知します。以下は、これで役割を果たすスニペットです。ShiftCtrl

Cスニペット:

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スニペット:

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

プログラムを実行してEscapeキーを押すと、コンソールに次のように表示されます。

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
#

Java関数を間違った方法で呼び出していることは知っていますが、どこが間違っているのかわかりません。Escape出力からのように、キーを押して予期しないエラーが発生した場合を満たしています。

ログファイルへのリンク

編集:

mavroprovatoによる回答の後、私はまだ同じエラーを受け取ります。

私はこのように編集しました:

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

編集:

COMPLETECODEバージョン1

COMPLETECODEバージョン2

4

3 に答える 3

4

JNIEnv使用されているJVMが有効ではないため、JVMがクラッシュしています。コードには他にも問題があります。

Sun JNIのドキュメントは、スレッドに関する非常に優れた情報を提供しています。

ここに明らかないくつかの部分があります:

コードに関数を作成JNI_OnLoadします。ライブラリがロードされるときに呼び出されます。JavaVM次に、ポインタをキャッシュします。これは、スレッド間で有効だからです。別の方法は関数を呼び出すことですが、私は最初(*env)->GetJavaVMinitializeJNIVars関数を好みます。

を呼び出すことによりinitializeJNIVars、参照を保存できます。objObj = (*env)->NewGlobalRef(obj)

でポインタLowLevelKeyboardProcを取得する必要があります:env

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


編集

OK、これが機能するために追加する必要のあるコードです。私はそれを自分で試しましたが、機能します。注意:私はあなたのコードが実際に何をしているのかを分析していないので、それを機能させるためにいくつかの修正を行いました。

他のグローバル変数の中にこれらの変数を追加します。

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

、、、および 変数を削除してcls、代わりに私のものを使用できます。midEnvObj

JavaVMポインタをキャッシュするJNI_OnLoadメソッドを作成します。

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

initializeJNIVarsのように変更します。

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

そして最後に、LowLoevelKeyboardProcコードに以下を追加する必要があります。

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

unregisterWinHookオブジェクトをGCできるように、グローバル参照を削除する必要があります。

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

以上です。

于 2012-06-05T11:47:48.553 に答える
3

Stringパラメータを受け取って渡すjavaメソッドを呼び出すことはできないと思いますchar*最初にNewStringUTFを呼び出す必要があります。

于 2012-06-05T10:50:39.737 に答える
0

オペレーティングシステムでUAC機能が有効になっていることが原因だと思います。これはJava6のバグでした。詳細については、これをお読みください

私がこれを言う理由は、Escキーへのイベントが正しく発生し、Javaメソッドの呼び出しが行われるとすぐに問題が始まるためです。

于 2012-06-05T10:47:51.207 に答える