gpt4 book ai didi

java - 这个对java方法的调用有什么问题?

转载 作者:搜寻专家 更新时间:2023-10-31 19:48:21 25 4
gpt4 key购买 nike

我正在尝试从代码中调用 Java 方法。 C 代码监听 EscapeShiftCtrl 键按下,然后调用 Java 方法告知按下了哪个键。以下是在其中发挥作用的片段。

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 键然后发生意外错误的情况。

Link to the LOG FILE

编辑:

mavroprovato回答后我仍然遇到同样的错误。

我是这样编辑的:

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

编辑:

COMPLETE CODE version 1

COMPLETE CODE version 2

最佳答案

JVM 正在崩溃,因为使用的 JNIEnv 无效。代码还存在其他问题。

Sun JNI documentation提供了关于线程的非常好的信息。

这里有一些显而易见的部分:

在您的代码中创建一个 JNI_OnLoad 函数。加载库时将调用它。然后缓存 JavaVM 指针,因为它跨线程有效。另一种方法是在 initializeJNIVars 函数中调用 (*env)->GetJavaVM,但我更喜欢第一个。

在您的 initializeJNIVars 中,您可以通过调用 Obj = (*env)->NewGlobalRef(obj) 来保存 obj 引用。

LowLevelKeyboardProc 中,您必须获取 env 指针:

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


编辑

好的,这里是您应该添加的代码以使其正常工作,我已经亲自尝试过并且可以正常工作。 注意:我没有分析您的代码实际在做什么,所以我只是做了一些修复以使其正常工作。

将这些变量添加到您的其他全局变量中:

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

您可以删除您的 clsmidEnvObj 变量并改用我的。

创建缓存 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);

就是这样。

关于java - 这个对java方法的调用有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10895826/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com