Java Native Interface (JNI)

For a complete introduction, including samples, can be found at Sun's JNI Developer's Tutorial. This page gives a brief overview of using JNI.

Topics

 

Shared Library

[ TOP ]

JNI requires a dynamic library (*.DLL, *.so, *.dynlib, etc.) with native function names matching the fully qualified names of the Java function names. Creating a dynamic library varies from system to system, compiler to compiler. A good tool to use is GNU's libtool, which "hides the complexity of using shared libraries behind a consisent, protable interface." *1

Creating a shared object, without libtool, on a Linux system using gcc, looks something like:

Example Makefile
    [ ... ]

CFLAGS=-I$(JAVA_HOME)/include/linux
LDFLAGS=-L$(JAVA_HOME)/jre/lib/glnx86
LINK.cc = gcc $(CFLAGS) $(LDFLAGS)
LIBS = 
JNI = /usr/local/lib/jni

# -- JNI library
#
$(JNI)/libSomethingImpl.so: SomethingImpl.o
        $(LINK.cc) -shared -PIC -o $(JNI)/libSomethingImpl.so SomethingImpl.o $(LIBS)


    [...]
 

Example: Java code

[ TOP ]

To implement a native interface, the Java code and the native code need to match exactly. the easiest way to do this is to implement the Java functions that interact with the native code, and then use the javah tool to create the correct C code header files. For example:

Example Java implementation
package  edu.ucsb.cs.jicos.external.services.example;

import edu.ucsb.cs.jicos.services.external.services.ProxyServiceExternal;

public class SomethingImpl extends ProxyServiceExternal
{
	[ ... ]

    public boolean doSomethingUseful( String param )
    {
        boolean result = false;

        if( null != param )
	{
	    result = doSomething( param );
	}

	return( result );
    }

	[ ... ]

    private static native boolean doSomething( String param );

	[ ... ]
}
 

Example: C (native) code

[ TOP ]

With the matching C (native) implementation:

Example C implementation
#include  
#include  SomethingUseful
    [ ... ]

	JNIEXPORT jboolean JNICALL 
Java_edu_ucsb_cs_jicos_services_external_services_example_SomethingImpl_doSomething(
    JNIEnv* jniEnv,
    jclass  jThis,
    jstring param
){
    jboolean  success = false;

	do something useful

    return( success );
}

    [ ... ]
 

Running the example

[ TOP ]

Since dynamic libraries get loaded and linked at run time, the program needs to know where to find the JNI implementation, and any other shared library. this is done with the java.library.path property. Assuming that the library is in the /usr/local/lib/jni and the java classes are located in ./build, the correct invocation would be:

Java Test program: Tester.java
package  edu.ucsb.cs.jicos.external.services.example;

public class Tester
{
    public static void main( String[] cmdLine )
    {
        String string = null;
	switch( cmdLine.length )
	{
	    case 0:
	        break;

	    default:
	        string = cmdLine[0];
		break;
	}

	SomethingImpl somethingImpl = new SomethingImpl();

	if( somethingImpl.doSomethingUseful( string ) )
	{
	    System.out.println( "Success!" );
	}
	else
	{
	    System.out.println( "failure" );
	}
    }
}
with command line invocation:
Example command line invocation
% java -Djava.library.path=/usr/local/lib/jni -classpath build \
            edu.ucsb.cs.jicos.services.external.services.example.Tester



 
*1: GNU Libtool Project. http://www.gnu.org/software/libtool/libtool.html