I\'m trying to make this simple example work:
import java.io.*;
public class Timer {
public static void main(String[] args) {
setTimer(new Runna
The problem is the invalid genv and gobj. genv and gobj are valid between variable set and leaving Java_Timer_setTimer function. You can get env* from the current jvm and make the obj to global ref. I define the new variables:
static JavaVM *jvm = NULL;
static jobject callback = NULL;
In Java_Timer_setTimer:
/* find the current jvm */
(*env)->GetJavaVM(env, &jvm);
/* upgrade callback to global ref */
callback = (*env)->NewGlobalRef(env, obj);
In handle, use jvm to attach current thread and invoke callback:
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);
}
Finally, we make it runnable:
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
The completed source code are:
#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.
}
}