Chapter 6. Jamaica and the Java Native Interface (JNI)

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 with other 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 loaded libraries are usually not available on small embedded systems that do not provide a file system, a different approach is taken by Jamaica. Instead of loading a library at runtime, it is preferable to include the native code statically into the application itself, i. e., link the native object code directly with the application.

The Builder allows direct linking of native object code with the created application through the option -object <file>. If more than one object file should be linked multiple file can be provided by separating the file names with spaces and enclosing the whole option argument into ". 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. This example does nothing but write a value to hardware register using a native method. The Java code might look like Figure JNITest.java:

For writting native code Jamaica provides a handy little tool, jamaicah, which generates a C header file with all native function prototypes for a given class file. Note that jamaicah operates on Java class files, so the class files have to be created first. For the example here, SUN Solaris's javac is used, but jikes or any other java-to-bytecode compiler would be fine, too. Figure JNITest.h is generated by:

  > 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 typing errors, just copy the function declarations from the generated header file.

To generate an object file a C compiler, e. g. gcc - the GNU C compiler, is used. Any other C compiler should also be fine. Note that the include search directories provided with the option -I may be different on your system.

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

For Windows user using the MinGW gcc:

  >c:\mingw\bin\gcc -Ic:\programs\jamaica\target\mingw\include 
  -c JNITest.c

Finally, the Builder can be called to generate a binary file which contains all necessary classes as well as the object file with the native code from JNITest.c. The Builder is called by:

  > jamaica -smart -object=JNITest.o JNITest
      
Jamaica Builder Tool 2.1beta Release 2
Generating code for target 'linux-gnu-i686'
 + 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 \
  -L/usr/X11/lib \
  -L/usr/lib \
  -lX11 -lpthread -lm -lm -lpthread -ljamaicas32 \
  -lX11 -lpthread -lm -lm -lpthread -ljamaicas32
/usr/bin/strip JNITest                                                          
    
  

The created application can be executed just like any other executable:

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