23 October, 2005
Native Methods with the Java Native Interface
The Java Native Interface (JNI) allows you to integrate native code with Java programs. Native methods are methods implemented in another programming language (such as C or assembly language).
Reasons for using the JNI:
- Platform-specific features can be accessed that aren't available through the Java Virtual Machine (JVM).
- Existing libraries and applications written in other programming languages can be accessed by Java applications.
- Optimization of time-critical code can be done in a low-level programming language such as assembly.
The JNI also allows the native methods to create and manipulate Java objects.
Example Java Code
The following is an example class called HelloWorld.
public class HelloWorld
{
public native void hello();
static
{
System.loadLibrary("hello");
}
public static void main(String[] args)
{
new HelloWorld().hello();
}
}
Compile and Create the JNI Header File
After compiling HelloWorld.java, use javah to create a JNI header file by typing javah -jni HelloWorld at the command prompt.
This provides a C function signature for the implementation of hello() defined in the HelloWorld class.
The resulting HelloWorld.h should look something like the following:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: hello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_hello(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Native Method Implementation in C
Now we need to implement the hello() method in C.
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL
Java_HelloWorld_hello(JNIEnv *env, jobject obj)
{
printf("Hello world!
"); return; }
Create a Shared Library
This will vary from platform to platform.
Linux or Solaris
On Linux or Solaris we build libhello.so using the following.
You may have to modify the include path to correspond to the location of Java on your machine.
Here I've used the environment variable $JAVA_HOME for convenience.
$ cc HelloWorld.c -I$JAVA_HOME/include -I$JAVA_HOME/include/linux
-shared -fpic -o libhello.so
$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
Win32
In Win32 we build hello.dll using something like MS Visual C++ 4.0:
cl -Ic:javainclude -Ic:javaincludewin32
-LD HelloWorldImp.c -Fehello.dll]]>
Run the Program
Now it's time to see if our native method works using java HelloWorld.
You may get an error message that looks like this:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1491)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:834)
at HelloWorld.<clinit>(HelloWorld.java:7)
This is probably because your library path isn't set up correctly.
In UNIX you generally need to set the environment variable LD_LIBRARY_PATH so that it includes the directory containing libhello.so.