C and Java: The Java Native Interface (JNI)

 < Day Day Up > 



C++ and Java: The Java Native Interface (JNI)

C++ native code can be called from a Java program. This is accomplished using the Java Native Interface (JNI). With Java and JNI you write a Java program that dynamically loads a native library that contains one or more native methods declared in the Java class. The dynamic link library can be created using C++. The next section describes the process in detail and then gives both a Win32 and Macintosh OSX example.

Steps To Create a JNI C++ Program

This section lists the steps required to create a JNI C++ program. The steps are further illustrated in figure 18-20.

Step 1 - Create a Java source file that declares a class with one or more native methods. In addition to any native methods this class requires it also must also load the native dynamic library module using the System.loadLibrary() function.

Step 2 - Compile the Java source file to create a .class file.

Step 3 - Use the javah compiler with the -jni switch to automatically create a header file for use in your C++ program.

Step 4 - Create a C++ source file that implements the native method.

Step 5 - Compile the C++ source file to create a dynamic link library that exports the native method.

Step 6 - Run the Java program using the java virtual machine and do a victory dance!

click to expand
Figure 18-20: Steps to Create a Java Native Interface (JNI) Program

Everything goes smooth up until around step 6. Success here depends on what operating system you are running since the name of the library file the java virtual machine is looking for is - you guessed it - implementation dependent. Consult the Java JNI documentation to learn how to properly form dynamic library names in your computing environment. The next section provides a complete JNI example targeting the Win32 environment.

Win32 JNI Example

In this section I will show you how to create a complete JNI program that targets the Win32 platform. This example will entail creating a Java class named SayHi. The SayHi class will declare a native method named sayHi(). The sayHi() method will be implemented in C++ and saved in a Win32 dynamic link library (DLL). To call the sayHi() method the SayHi class must first load the DLL. These steps are described in detail below.

Step 1: Create Java Source File

Start your JNI project by creating a Java source file that declares one or more native methods. Example 18.11 gives the source code for a Java class named SayHi.

Listing 18.11: SayHi.java

start example
  1  public class SayHi{  2  3     public native void sayHi();  4  5     public void loadLibrary(String lib_name){  6        System.loadLibrary(lib_name);  7     }  8  9     public static void main(String args[]){ 10       SayHi sh = new SayHi(); 11       sh.loadLibrary(args[0]); 12       sh.sayHi(); 13     } 14  }
end example

On line 3 the SayHi class declares a native method named sayHi() that is public, returns void, and takes no function arguments. Note that this is only a function declaration as opposed to an ordinary Java method which normally combines both the function declaration and definition within the class body.

On line 5 a function named loadLibrary() is defined. The loadLibrary() function will take a String argument that represents the name of the DLL the SayHi class must load before calling the sayHi() function. The loadLibrary() function then calls the System.loadLibrary() function using the lib_name parameter. Using a class instance function to load the dynamic library allows the overhead associated with loading the library to be deferred until it is actually needed.

The main() function begins on line 9. A new SayHi object is created on line 10. Next, the loadLibrary() function is called using the library string name contained in arg[0]. Finally, the sayHi() function is called on line 12.

Step 2: Compile Java Source File

Use the Java compiler to compile the SayHi.java file. The Java compiler is invoked using the javac command as shown in figure 18-21.

click to expand
Figure 18-21: Compiling SayHi.java

Compiling the SayHi.java file results in a Java class file names SayHi.class as shown in figure 18-22.

click to expand
Figure 18-22: Compiling SayHi.java Results in SayHi.class

Step 3: Create Header File

To create a C++ implementation of a Java native method you must have a header file that declares the C++ version of the method. The Java platform supplies a command line tool named javah that can be used to automatically create these header files. The javah tool requires a Java class file. It automatically assumes the .class file extension. Figure 18-23 shows the javah tool being used to create the SayHi.h header file.

click to expand
Figure 18-23: Using javah to Create the SayHi.h Header File

Figure 18-24 shows the results of creating the SayHi.h header file with the javah command line tool.

click to expand
Figure 18-24: Results of Creating SayHi.h Using javah Command Line Tool

Example 18.12 shows the contents of the SayHi.h header file.

Listing 18.12: SayHi.h

start example
  1  /* DO NOT EDIT THIS FILE - it is machine generated */  2  #include <jni.h>  3  /* Header for class SayHi */  4  5  #ifndef _Included_SayHi  6  #define _Included_SayHi  7  #ifdef __cplusplus  8  extern "C" {  9  #endif 10  /* 11   * Class:         SayHi 12   * Method:        sayHi 13   * Signature: ()V 14   */ 15  JNIEXPORT void JNICALL Java_SayHi_sayHi 16    (JNIEnv *, jobject); 17 18  #ifdef __cplusplus 19  } 20  #endif 21  #endif
end example

The actual native function declaration appears on lines 15 and 16. For a complete discussion on the purpose and use of the JNIEnv* and jobject parameters refer to the JNI references listed at the end of the chapter.

Now, with the header file generated you can create the SayHi() function C++ implementation file.

Step 4: Create C++ Source File

Example 18.13 shows the source code for the sayhi.cpp file.

Listing 18.13: sayhi.cpp

start example
 1  #include "jni.h" 2  #include "SayHi.h" 3  #include <iostream> 4  using namespace std; 5 6  JNIEXPORT void JNICALL Java_SayHi_sayHi (JNIEnv * env, jobject jo){ 7 8    cout<<"C++ SayHi() function working fine!"<<endl; 9  }
end example

The sayhi.cpp file needs to include the jni.h and the freshly-generated SayHi.h header files in addition to the iostream header file. With the sayhi.cpp file in hand you can now create a DLL.

Step 5: Compile C++ Source File to Create Dynamic Link Library

To create the Win32 DLL I will use Metrowerks CodeWarrior Release 5 and start with an empty project. I will then add the sayhi.cpp file and any libraries needed to create the DLL.

Figure 18-25 shows a blank CodeWarrior project window named JNI_Test. Figure 18-26 shows the sayhi.cpp file added to the blank project.

click to expand
Figure 18-25: Blank CodeWarrior Project

click to expand
Figure 18-26: sayhi.cpp Added to Blank Project

To generate a Win32 DLL using Metrowerks CodeWarrior you must add several important libraries. Figure 18- 27 shows the blank project window after adding the necessary libraries.

click to expand
Figure 18-27: Blank Project Window Showing Added Library Files

Almost there. Before generating the DLL you must set some target settings. Figure 18-28 shows the target settings window with the necessary settings.

click to expand
Figure 18-28: Target Settings Widow

Notice in the Target Settings window the Project Type is set to Dynamic Link Library (DLL) and the File Name is set to SayHi.dll.

When the necessary target settings are completed you can make the project to generate the SayHi.dll file. Figure 18-29 shows a directory listing after compiling the SayHi project.

click to expand
Figure 18-29: Directory Listing Showing SayHi.dll

Step 6: Run Java Program

Once you have generated the SayHi.dll file successfully you can run the SayHi Java application. The name of the SayHi dynamic link library must be supplied on the command line when the SayHi Java application is run. The command line to execute the SayHi program looks like this:

java SayHi SayHi

Notice the name of the dynamic link library is just SayHi and not SayHi.dll. The System.loadLibrary() function will complete the library name by appending the .dll extension to the library name you supply. Figure 18-30 shows the results of running the SayHi Java application.

click to expand
Figure 18-30: Results of Running the SayHi Java Application

Macintosh OSX JNI Example

In this section I will show you how to create the Macintosh OSX version of the same SayHi JNI program as shown in the previous section. The steps are the same as those listed in the Win32 example with two major exceptions. 1) The name of the dynamic link library will be different and, 2) the development environment used to create the dynamic link library will be different.

Step 1: Create Java Source File

The same SayHi.java file used in the previous section will be used in this example. Refer to example 18.11 for the SayHi.java source code.

Step 2: Compile Java Source File

The Macintosh OSX operating system comes with a set of developer tools that includes the Java platform for OSX. The command line tools are the same for OSX as they are for Microsoft Windows. Compile the SayHi.java file to produce the SayHi.class file.

Step 3: Create Header File

Use the javah command line tool to create the SayHi.h header file. This file should look exactly like the SayHi.h file created using the Win32 version of javah.

Step 4: Create C++ Source File

The same C++ source file sayhi.cpp used in the Win32 example is used here as well. Refer to example 18.13 for the source code listing of sayhi.cpp.

Step 5: Compile C++ Source File to Create Dynamic Link Library

OK, here is where things go a little differently. I will use the GNU C++ compiler to create the OSX version of the dynamic link library. The GNU C++ compiler comes with Macintosh OSX but you might have to install it separately. If you have not installed the OSX developer tools you should do so now.

To create the dynamic link library with the GNU C++ compiler use the following command line:

g++ -I <java include file path> -dynamiclib -o <output file name><C++ source file to compile>

The -I switch tells the GNU C++ compiler where to find include files. You will have to use this compiler switch to tell the compiler where to find the jni.h header file as it will most likely not be located in the environment's normal include path.

The -dynamiclib switch tells the compiler to produce a dynamic link library. The -o switch tells the compiler what to name the output file. The name of the OSX version of the dynamic link library should be lib<lib_name>.jnilib. In other word, the Java System.loadLibrary() function, when run in the OSX environment, will take the name of the library (SayHi) and prefix it with lib and suffix it with .jnilib to form the complete library name. Therefore, it will look for a library file named libSayHi.jnilib. You must instruct the GNU compiler to produce a dynamic link library file named libSayHi.jnilib.

Finally, tell the GNU compiler the name of the C++ file to compile. Figure 18-31 shows the GNU C++ complier being invoked from a Macintosh OSX terminal window.

click to expand
Figure 18-31: Compiling sayhi.cpp Using g++ to Generate an OSX Dynamic Link Library

Figure 18-32 shows the directory listing that includes the libSayHi.jnilib dynamic link library file.

click to expand
Figure 18-32: Directory Listing Showing libSayHi.jnilib File

Step 6: Run Java Program

All that is left to do is run the SayHi Java program. This is done in exactly the same fashion as the Win32 example. Use the java command line tool giving the name of the SayHi class and the name of the SayHi dynamic link library. Figure 18-33 shows the results of running the Java SayHi program.

click to expand
Figure 18-33: Results of Running SayHi Java Program in an OSX Terminal Window

When To Use JNI

There is a certain amount of overhead involved with making a native function call from a Java program. If you are writing a native function with the intention of calling it frequently, say, from the body of an often-repeated loop, a native method may not be the optimum solution, especially if the function is small and takes only a fraction of the time to execute vs. the time it takes to make the function call. If, however, the function does something significant and is called infrequently, then JNI may be the way to go.

Quick Review

C++ can be used to write functions that target specific hardware platforms. These native functions can be called from a Java program using the Java Native Interface. Most of the steps involved in creating a JNI program are portable across computing platforms with the exception of how the native dynamic link library is created and how it is named.



 < Day Day Up > 



C++ for Artists. The Art, Philosophy, and Science of Object-Oriented Programming
C++ For Artists: The Art, Philosophy, And Science Of Object-Oriented Programming
ISBN: 1932504028
EAN: 2147483647
Year: 2003
Pages: 340
Authors: Rick Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net