Introduction to JNI
Java Native Interface is a Java API specification that allows programmers to write Java programs which can interface with Native programs, which are specific to a particular platform like Windows or Unix. Using JNI, programmers can leverage the platform dependent features within their Java programs, which otherwise they cannot invoke with normal Java facilities. JNI even allows programs written in languages like C / C++ to access Java objects. This tutorial is helpful for programmers who know the basics of Java programming and want to use the JNI API to access Native libraries.
A simple JNI Example
This simple example demonstrates how a Java program interfaces with Native code written in language like C / C++. I have tested this example using “Borland C++ 5.5 Compiler” on a Windows 2000 system. The steps mentioned below refer commands specific to Borland C++. Other compilers and tools can also be used to write Native libraries.
Step 1. Write a HelloWorld.java file
The complete source code is -
class HelloWorld {
public native void displayHelloWorld();
static {
System.loadLibrary('helloworldimp');
}
public static void main(String<> args) {
new HelloWorld().displayHelloWorld();
}
}
The above Java class loads a Window’s DLL helloworldimp.dll, and invokes a function displayHelloWorld which will be implemented in C.
The declaration
public native void displayHelloWorld(); specifies that displayHelloWorld function is a native function.
Compile the above Java file with Java compiler ‘javac’
javac HelloWorld.java
This generates a file called HelloWorld.class .
Step 2. Generate a C header file
From the HellowWorld.class file generated in
Step 1., a C header file is generated with the command.
javah -jni -classpath . HelloWorld
This command is available in JAVA_HOME\bin directory. This directory can be put in the system PATH variable.This generates a file HelloWorld.h.
The HelloWorld.h file has the contents
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern 'C' {
#endif
/*
* Class: HelloWorld
* Method: displayHelloWorld
* Signature: ()
*/
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
The above header file will be included in the C program later.
Step 3. Write a C program which implements the function
displayHelloWorld()
Source code for program helloworldimp.c
#include
#include 'HelloWorld.h'
#include
JNIEXPORT void JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf('Hello world!\n');
return;
}
Compile the above file with command
bcc32 -c helloworldimp.c
This command will produce the object file helloworldimp.obj
Note -- The HelloWorld.h file generated in Step 2. is imported in this C file.
Step 4. Generate Window’s DLL
Generate a Window’s DLL with the command
bcc32 -tWD helloworldimp.obj
This will generate a file helloworldimp.dll
Step 5. Run the Java program with ‘java’ command
java HelloWorld
This command should produce output
Hello world!
Conclusion
It is evident that JNI offers a powerful mechanism to interface Java programs with Native libraries. There are requirements when Java programs need to access native libraries, for e.g. a Java program may want to access a Window’s registry or it needs to access a device driver written in C. JNI programming can become quite useful when execution time is critical, because Native code executes faster than its Java counterpart. The C / C++ programs which intend to expose themselves to Java programs should be written keeping JNI model in mind. This is evident in Step 3. of the tutorial.
I hope this article was useful to the readers. Anybody is welcome to write his or her comments about this article to me at
mukul_gandhi@yahoo.com