Chapter 6. Jamaica and the Java Native Interface

Table of Contents
Using JNI
JamaicaH Usage

The Java Native Interface (JNI) is a standard mechanism for inter-operability between Java and native code, i.e., code written in non-portable system programming languages like C. Jamaica implements Version 1.2 of the Java Native Interface. Since JNI provides hundreds of routines, including support for JNI would pose too big an overhead on those applications that are not using it. This is why JNI support must be activated explicitly by giving setting the option -jni when using the builder.

Using JNI

Native code that is interfaced through the JNI interface is typically stored in shared libraries that are dynamically loaded by the virtual machine when the application uses native code. Since dynamically loading libraries is not possible on small embedded systems that don't provide a file system, a different approach is taken by Jamaica. Instead of loading a library, it is preferable to have the native code be part of the application itself, i.e., to link the native object code directly with the application.

The Jamaica Builder allows direct linking of native object code with the application through the option -object <file>. All object files containing native code have to be presented to the builder using this option in addition to the option -jni that enables the support for JNI.

To build an application that uses the native code on a target that requires manual linking, it might also be required to provide these object files to the linker, and it might even be required to provide a specific Jamaica JNI-object file that contains the JNI support. Here is a short example on the use of the Java Native Interface with Jamaica. We have a small application that does nothing but write a hardware register using a native method.The Java code might look like Figure JNITest.java:

Jamaica provides a handy little tool, jamaicah, which generates a C header file for us. Note that jamaicah operates on Java class files, so we have to create one first. For this example, we use SUN's javac, but jikes or any other java-to-bytecode compiler would be fine. Here, we generate Figure JNITest.h

> javac JNITest.java
> jamaicah JNITest

The native code is implemented in the following routine written in C. See Figure JNITest.c for an example. Note that the mangling of the Java name into a name for the C routine is defined in the JNI specification. In order to avoid typos, just copy the function declarations from the generated header file.

Now, we have to generate a C object file. We use gcc, the GNU compiler here. Any other C compiler should also be fine. Note that the include directory may be different on your system.

> gcc -I /usr/local/jamaica/target/linux-gnu-i686/include -c JNITest.c

Finally, we can call the Jamaica Builder to generate a binary file which contains all necessary classes as well as our C object file JNITest.c. We have to tell the Builder explicitly that we need this object.

> jamaica -smart -object JNITest.o JNITest
Jamaica Builder Tool
 + JNITest__.c
 + JNITest.makefile
Classfile compaction gain: 92.59319% (378368 ==> 28025)
gcc -O2 -Wall -g -O2  -o JNITest__.o -c JNITest__.c -DNDEBUG -DJAMAICA_SHORT_MODEL -I /usr/local/jamaica/target/linux-gnu-i686/include
gcc  -o JNITest JNITest.o JNITest__.o -L/usr/local/jamaica/target/linux-gnu-i686/lib -lX11 -L/usr/X11/lib -lpthread -lm -L/usr/lib -lm -lpthread -ljamaicas32 -lX11 -L/usr/X11/lib -lpthread -lm -L/usr/lib -lm -lpthread -ljamaicas32
/usr/bin/strip JNITest                                                          

And the resulting application can be executed just like a normal builder Java application:

> ./JNITest
Now we could write the value 65632 into memory address fc000008
Result: 65632