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

Table of Contents
Using JNI
Jamaicah usage

The Java Native Interface (JNI) is a standard mechanism for interoperability 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 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 better to statically include the native code 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>. Multiple files can be linked. Separate the file names with spaces and enclose the whole option argument within '"' (double quotes). All object files containing native code should be presented to the Builder using this option in addition to the option -jni that enables the support for JNI.

Building an application using native code on a target requiring manual linking may require providing these object files to the linker. Here is a short example on the use of the Java Native Interface with Jamaica. This example simply writes a value to a hardware register using a native method. The Java code might look like the code shown in Figure 9-1.

Jamaica provides a tool, jamaicah, for generating C header files that contain the function prototypes for all native methods in a given class. Note that jamaicah operates on Java class files, so the class files have to be created first using jamaicac as described in Chapter 4. The include file JNITest.h as shown in Figure 9-2 is generated by the commands:

  > jamaicac JNITest.java
  > jamaicah JNITest
      
Reading configuration from '/usr/local/jamaica/etc/jamaicah.conf'...
 + JNITest.h (header)
    
  

The native code is implemented in the following routine written in C. See Figure 9-3 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.

A C compiler is used to generate an object file. Here, gcc - the GNU C compiler is used, but other C compilers should also work. Note that the include search directories provided with the option I may be different on your system.

For Unix user using gcc:

  > 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 -object=JNITest.o JNITest
      
Reading configuration from '/usr/local/jamaica/etc/jamaica.conf'...
Jamaica Builder Tool 3.0 Release 1 
Generating code for target 'linux-gnu-i686', optimisation 'none'
 + JNITest__.c
 + JNITest__.h
Class file compaction gain: 66.33531% (7189394 ==> 2420287)
 + JNITest__nc.o
 * C compiling 'JNITest__.c'
 * linking
 * stripping
    
  

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