Friday, December 12, 2008

Native Methods

Native Methods

Although it is rare, occasionally, you may want to call a subroutine that is written in a language other than Java. Typically, such a subroutine exists as executable code for the CPU and environment in which you are working—that is, native code.

 

For example, you may want to call a native code subroutine to achieve faster execution time. Or, you may want to use a specialized, third-party library, such as a statistical package.

 

However, because Java programs are compiled to bytecode, which is then interpreted (or compiled on-the-fly) by the Java run-time system, it would seem impossible to call a native code subroutine from within your Java program. Fortunately, this conclusion is false. Java provides the native keyword, which is used to declare native code methods.

 

Once declared, these methods can be called from inside your Java program just as you call any other Java method.

 

To declare a native method, precede the method with the native modifier, but do not define any body for the method.

 

For example:

 

public native int meth() ;

 

After you declare a native method, you must write the native method and follow a rather complex series of steps to link it with your Java code. Most native methods are written in C. The mechanism used to integrate C code with a Java program is called the Java Native Interface (JNI). This methodology was created by Java 1.1 and then expanded and enhanced by Java 2. (Java 1.0 used a different approach, which is now completely outdated.) A detailed description of the JNI is beyond the scope of this book, but the following description provides sufficient information for most applications.

 

The precise steps that you need to follow will vary between different Java environments and versions. This also depends on the language that you are using to implement the native method. The following discussion assumes a Windows 95/98/XP/NT/2000 environment. The language used to implement the native method is C.

 

The easiest way to understand the process is to work through an example.

To begin, enter the following short program, which uses a native method called test( ):

 

// A simple example that uses a native method.

public class NativeDemo {

int i;

public static void main(String args[]) {

NativeDemo ob = new NativeDemo();

ob.i = 10;

System.out.println("This is ob.i before the native method:" +

ob.i);

ob.test(); // call a native method

System.out.println("This is ob.i after the native method:" +

ob.i);

}

// declare native method

public native void test() ;

// load DLL that contains static method

static {

System.loadLibrary("NativeDemo");

}

}

 

Notice that the test( ) method is declared as native and has no body. This is the method that we will implement in C shortly. Also notice the static block. As explained earlier in this book, a static block is executed only once, when your program begins execution (or, more precisely, when its class is first loaded). In this case, it is used to load the dynamic link library that contains the native implementation of test( ). (You will see how to create this library soon.)

 

The library is loaded by the loadLibrary( ) method, which is part of the System class. This is its general form:

 

static void loadLibrary(String filename)

 

Here, filename is a string that specifies the name of the file that holds the library. For the Windows environment, this file is assumed to have the .DLL extension.

 

After you enter the program, compile it to produce NativeDemo.class. Next, you must use javah.exe to produce one file: NativeDemo.h. (javah.exe is included in the SDK.) You will include NativeDemo.h in your implementation of test( ). To produce NativeDemo.h, use the following command:

 

javah -jni NativeDemo

 

This command produces a header file called NativeDemo.h. This file must be included in the C file that implements test( ). The output produced by this command is shown here:

 

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class NativeDemo */

#ifndef _Included_NativeDemo

#define _Included_NativeDemo

#ifdef _ _cplusplus

extern "C" {

No comments: