この簡単な例を機能させようとしています:
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");
}
}
コードは簡単です。とsetTimer
を使用して JNI/C/Linux でプログラムします。例では、毎秒ティックを出力する必要があります。SIGALRM
setitimer
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 segfaults を起動すると、次のメッセージが表示されます。
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00e9531c, pid=5742, tid=3077924544
#
...
なんで?