gpt4 book ai didi

java - 使用 JNI 将 java 与 C 计时器库进行接口(interface)

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:30:50 25 4
gpt4 key购买 nike

我正在努力使这个简单的示例起作用:

import java.io.*;

public class Timer {
public static void main(String[] args) {
setTimer(new Runnable() {
public void run() {
System.out.println("tick");
}
},
1000 /* msecs */
);
while (true) ;
}

native public static void setTimer(Runnable r, int msecs);

static {
System.loadLibrary("timer");
}
}

代码很简单。使用 SIGALRMsetitimer 在 JNI/C/Linux 中编程 setTimer。示例应每秒打印一次 tick

JNI 库被编程为:

#include <signal.h>
#include <sys/time.h>

#include "Timer.h"
#include "error.h"

static JNIEnv *genv;
static jobject gobj;

void handler(int s) {
jclass cls = (*genv)->GetObjectClass(genv, gobj);
jmethodID mid = (*genv)->GetMethodID(genv, cls, "run", "()V");
(*genv)->CallVoidMethod(genv, gobj, mid);
}

JNIEXPORT void JNICALL Java_Timer_setTimer
(JNIEnv *env, jclass cls, jobject obj, jint msecs) {
struct sigaction sa;
struct itimerval it;

sa.sa_flags = SA_RESTART;
sigemptyset (&sa.sa_mask);

genv = env;
gobj = obj;
sa.sa_handler = handler;
it.it_interval.tv_sec = msecs/1000;
it.it_interval.tv_usec = (msecs%1000)*1000;
it.it_value = it.it_interval;

if (sigaction (SIGALRM/*PROF*/, &sa, NULL) == -1
|| setitimer (ITIMER_REAL/*PROF*/, &it, NULL) == -1)
SysError("setTimer: sigaction, setitimer: couldn't init timer");
}

我正在使用信号链库以避免对 JVM 产生信号干扰:

LD_LIBRARY_PATH=. LD_PRELOAD=/usr/lib/jvm/java-6-openjdk/jre/lib/i386/libjsig.so java Timer

SIGALRM 第一次使用消息触发 JMV 段错误:

#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00e9531c, pid=5742, tid=3077924544
#
...

为什么?

最佳答案

问题是无效的 genv 和 gobj。 genv 和 gobj 在变量集和离开 Java_Timer_setTimer 函数之间有效。您可以从当前 jvm 获取 env* 并将 obj 设为全局引用。我定义了新变量:

static JavaVM *jvm = NULL;
static jobject callback = NULL;

在 Java_Timer_setTimer 中:

/* find the current jvm */
(*env)->GetJavaVM(env, &jvm);
/* upgrade callback to global ref */
callback = (*env)->NewGlobalRef(env, obj);

在句柄中,使用jvm附加当前线程并调用回调:

void handler(int s) {
if(jvm == NULL)
return ;
if(callback == NULL)
return ;

JNIEnv *env = NULL;
jint res;
res = (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
if(res < 0)
{
fprintf(stderr, "Attach VM Thread failed\n");
return ;
}

jclass cls = (*env)->GetObjectClass(env, callback);
jmethodID mid = (*env)->GetMethodID(env, cls, "run", "()V");
(*env)->CallVoidMethod(env, callback, mid);
(*jvm)->DetachCurrentThread(jvm);
}

最后,我们让它可以运行:

qrtt1@qrtt1-VirtualBox:/media/sf_VBoxSharedFolder/0Lab$ java -Djava.library.path=. -classpath bin Timer
tick Tue Jul 24 13:01:54 CST 2012
tick Tue Jul 24 13:01:55 CST 2012
tick Tue Jul 24 13:01:56 CST 2012
tick Tue Jul 24 13:01:57 CST 2012
tick Tue Jul 24 13:01:58 CST 2012

完整的源码是:

#include "Timer.h"
#include <jni.h>
#include <signal.h>
#include <sys/time.h>
#include <stdio.h>


static JavaVM *jvm = NULL;
static jobject callback = NULL;

void handler(int s) {
if(jvm == NULL)
return ;
if(callback == NULL)
return ;

JNIEnv *env = NULL;
jint res;
res = (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
if(res < 0)
{
fprintf(stderr, "Attach VM Thread failed\n");
return ;
}

jclass cls = (*env)->GetObjectClass(env, callback);
jmethodID mid = (*env)->GetMethodID(env, cls, "run", "()V");
(*env)->CallVoidMethod(env, callback, mid);
(*jvm)->DetachCurrentThread(jvm);
}

/*
* Class: Timer
* Method: setTimer
* Signature: (Ljava/lang/Runnable;I)V
*/
JNIEXPORT void JNICALL Java_Timer_setTimer
(JNIEnv *env, jclass cls, jobject obj, jint msecs)
{

struct sigaction sa;
struct itimerval it;

sa.sa_flags = SA_RESTART;
sigemptyset (&sa.sa_mask);

/* find the current jvm */
(*env)->GetJavaVM(env, &jvm);
/* upgrade callback to global ref */
callback = (*env)->NewGlobalRef(env, obj);

sa.sa_handler = handler;
it.it_interval.tv_sec = msecs/1000;
it.it_interval.tv_usec = (msecs%1000)*1000;
it.it_value = it.it_interval;

if (sigaction (SIGALRM/*PROF*/, &sa, NULL) == -1
|| setitimer (ITIMER_REAL/*PROF*/, &it, NULL) == -1)
{
// error.
}
}

关于java - 使用 JNI 将 java 与 C 计时器库进行接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11616362/

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