我的目标是从内核向用户空间中运行的Android服务发送信号。收到此信号后,服务应该向内核发出IOCTL回调。通过此ioctl调用从内核获取数据后,必须向用户显示。为此,我从我的Java服务调用一个本机方法,该方法注册sigaction结构,其中包括此信号的处理函数。此处理函数将进行IOCTL调用并调用Java函数将字符串传递给Java服务。
这是signal.java类
public class signal {
static{
System.loadLibrary("signal");
}
public native String hello();
public String messageMe(String s)
{
if(null != MainActivity.mUiHandler)
{
Message msgToActivity = new Message();
msgToActivity.what = 0;
msgToActivity.obj = s; // you can put extra message here
MainActivity.mUiHandler.sendMessage(msgToActivity);
}
System.out.println(s);
return s;
}
}
我需要从信号处理程序中调用这个“messageMe”函数。 这是注册sigaction结构的本机hello()函数。
JNIEXPORT jstring JNICALL Java_com_example_service_signal_hello
(JNIEnv * env, jobject obj) {
int configfd;
char buf[10];
/* setup the signal handler for SIG_TEST
* SA_SIGINFO -> we want the signal handler function with 3 arguments
*/
struct sigaction sig;
sig.sa_sigaction = receiveData;
sig.sa_flags = SA_SIGINFO;
sigaction(SIG_TEST, &sig,NULL);
}
receiveData是处理函数。在这里。
void receiveData(int n, siginfo_t *info,void* unused) {
char buf[200];
char *msg = "hello world";
int fd = -1;
if ((fd = open("/dev/my_device", O_RDWR)) < 0) {
perror("on");
return;
}
if(ioctl(fd, READ_IOCTL, buf) < 0)
perror("second ioctl");
jstring jstr = (*env)->NewStringUTF(env, buf);
jclass *clazz = (*env)->GetObjectClass(env, obj);
jmethodID messageMe = (*env)->GetMethodID(env,clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;");
jobject result = (*env)->CallObjectMethod(env,obj, messageMe, jstr);
printf("message: %s\n", buf);
} 这个处理函数应该调用Java函数“messageMe”并将它从内核读取的字符串作为参数传递。但它没有环境变量JNIEnv *和jobject obj。当我在hello()函数中维护这些变量的全局指针,并在这里使用它们时,它给出了NoClassDefFoundError。 我现在如何将此信号处理程序中的字符串发送到Java函数?
答案 0 :(得分:2)
我有以下全局变量。我缓存了这些对象以备将来使用。
JavaVM* vm;
static jclass cl;
static jobject ob;
在hello函数中,我对上述变量进行了全局引用。
JNIEXPORT jstring JNICALL Java_com_example_service_signal_hello
(JNIEnv * env, jobject obj) {
(*env)->GetJavaVM(env,&vm);
ob = (*env)->NewGlobalRef(env,obj);
jclass clazz = (*env)->FindClass(env,"com/example/service/signal");
cl = (*env)->NewGlobalRef(env,clazz);
}
现在我在处理函数
中使用了这些void receiveData(int n, siginfo_t *info,void* unused) {
//other code
JNIEnv* env = NULL;
if(vm==NULL)
return;
(*vm)->AttachCurrentThread(vm,&env,0);
jmethodID messageMe = (*env)->GetStaticMethodID(env,cl, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;");
jobject result = (*env)->CallStaticObjectMethod(env,cl, messageMe, jstr);
}
我做的一个改变是使用静态方法而不是正常方法。所以我没有必要使用该类的特定实例。如果方法不是静态的,则可以在CallObjectMethod中使用全局变量“ob”。
答案 1 :(得分:0)
据我所知,GetObjectClass
方法会返回jclass
,而不是jclass *
。
在receiveData
功能中,您应该替换
jclass *clazz = (*env)->GetObjectClass(env, obj);
通过
jclass clazz = (*env)->GetObjectClass(env, obj);