Wednesday, July 22, 2009

JNI example

A simple example of JNI


Java Native Interface (JNI) is a standard programming interface for writing Java native methods and embedding the JVM into native applications. Simply, it is a Java technology with which a Java application can call a method written with such as C, C++ and assembly.

Adopting JNI is very simple. You need two components -- a Java program, and a native library. The native library is written in other languages and compiled on corresonding platforms.

A function defined in the native library should be declared in Java code as a 'native' function. And the native library needs to be load in Java code with the System.loadLibrary method. The natvie function could be referced by other regular functions in the Java code.

Following is an example of the Java Code.

JNIFoo.java
===========

public class JNIFoo {
public native String nativeFoo();

static {
System.loadLibrary("foo");
}

public void print () {
String str = nativeFoo();
System.out.println(str);
}

public static void main(String[] args) {
(new JNIFoo()).print();
return;
}
}

# javac JNIFoo.java
# javah -jni JNIFoo

A file named as JNIFoo.h is created by running the above two commands. A function of 'JNIEXPORT jstring JNICALL Java_JNIFoo_nativeFoo (JNIEnv *, jobject)' is in the JNIFoo.h file. The function must be implemented in a source code file (e.g. a C file), and it is the actually entry to do what the funtion of natvieFoo() in Java code do.


foo.c
======

#include
#include
#include
#include
#include "JNIFoo.h"

JNIEXPORT jstring JNICALL Java_JNIFoo_nativeFoo (JNIEnv *env, jobject obj)
{
int i;
int ds_ret;

char* newstring;

jstring ret = 0;

newstring = (char*)malloc(30);

if(newstring == NULL)
{
return ret;
}

memset(newstring, 0, 30);

newstring = "foo: Test program of JNI.\n";


ret = (*env)->NewStringUTF(env, newstring);

free(newstring);

return ret;
}

JNI libraries are named with the library name used in the System.loadLibrary method of your Java code with a prefix and a suffix. On different OS, the prefix and suffix might be different.

On Solaris OS, it is prefixed by 'lib' and suffixed with '.so'

# cc -Kpic -G -o libfoo.so -I/usr/java/include -I/usr/java/include/solaris foo.c -z text

On Linux OS, it is prefixed by 'lib' and suffixed with '.so'.

# gcc -shared -fpic -o libfoo.so -I/usr/java/include -I/usr/java/include/linux foo.c

On Windows OS, it is prefixed by nothing and suffixed with '.dll'.
It could be compiled with Visual Studio automatically and create a file named as foo.dll.

On Mac OS, it is prefixed by 'lib' and suffixed with '.jnilib'.

# gcc -dynamiclib -o libfoo.jnilib -I/System/Library/Frameworks/JavaVM.framework/Headers foo.c -framework JavaVM




To run the JNI program locally, the following command is fine:

# java -Djava.library.path= JNIFoo

1 comment:

Anonymous said...

Excellent stuff.

Here is a JNI example using a windows dll

Windows JNI example