23 October, 2005

Native Methods with the Java Native Interface

0 Comments

Written by Jason Davies Topics: Java

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.

0 Responses to “Native Methods with the Java Native Interface”

Leave a Comment