views:

778

answers:

3

I would like to create a Java program to listen for and respond to events captured by a thread in C.
Can someone explain how this can be achieved using JNI, or point me to online tutorials?

Thank you.

+1  A: 

You can have the native code call a Java method to receive the event. There are several articles on JNI that can help you out, such as How to Call Java functions from C Using JNI.

David Crow
Hi David,If the native code were to call a Java method to receive the event, how then can I pass the control back to the main Java program? There has to be only one instance of the Java program that constantly monitors and responds to events captured by a C API. Please advise. Thank you.
Assuming the native code is the entry point for your app, then it would launch the JVM and execute the main method in your Java program. You could have this main method start a single, separate Java thread, which runs in the background and receives events through methods called by the C API.
David Crow
A: 

David, what if Java is the entry point?

fd2
+1  A: 

The JNI specification is required reading if you want to do any sort of JNI-programming.

There are two scenarios when calling Java code from C. In the first case, the Java program calls a native method, passing control to C. The C function receives as its first argument a JNIEnv pointer which is the primary handle used to access the JNI. A typical call from Java to C looks like this:

jenv->CallStaticMethod(jenv, cls, ...);

(Note that in C++, the calls are proper methods, so you don't need to pass jenv as the first argument.) This is rather straightforward; Java calls C which calls back into Java.

The second case is a little more complex, and has to be used when you have C-code which needs to make a "spontaneous" call into Java, i.e. not as a result of that code first being called from Java. This is typically the case where you have a native thread generating events (as in your case). You then need to use an part of the JNI referred to as the Invocation API. This API is used in two steps: first you request a reference to the JVM you want to call (some JVM implementations support multiple JVMs in the same process), and the second step is to request a JNIEnv pointer in order to make calls into the JVM.

In order to get a JNIEnv pointer to make calls into the JVM, the native thread needs to "attach" itself to the JVM. This is done in order to make the JVM "aware" of the thread, and after attaching a thread to the JVM, the thread can be thought of as being any other Java thread (in fact, I'm not sure that there are any real differences). If you inspect the JVM's threads in a debugger, the native thread will show up as any other thread. Note that you can mark the native thread as being a daemon thread, so when the JVM exits, the thread will be killed.

Note, however, that you will need to take proper precautions when doing things in a Unix signal handler. I'd recommend not calling into Java directly from a signal handler.

JesperE