This chapter will answer the following questions:
In this chapter, we will explain how you can invoke native methods in Java applications using the Java Native Method Interface (JNI). We will begin by discussing how the JNI works in the JDK 1.1. We will then discuss the native keyword and how any Java method can become a native method. Finally, we will examine the JDK's javah tool, which is used to generate C header files for Java classes.
In order to achieve Java's main goal of platform independence, Sun did not standardize its implementation of the Java Virtual Machine; in other words, Sun did not want to rigidly specify the internal architecture of the JVM, but allowed vendors to have their own implementations of the JVM. This does not preclude Java from being platform-independent, because every JVM implementation must still comply with certain standards needed to achieve platform independence (such as the standard structure of a .class file). The only problem with this scenario is that accessing native libraries from Java apps becomes difficult, since the run-time system differs across the various JVM implementations. For that reason, Sun came up with the JNI as a standard way for accessing native libraries from Java apps.
The way native methods are accessed from Java apps changed in the JDK 1.1. The old way allowed a Java class to directly access methods in a native library. The new implementation uses the JNI as an intermediate layer between a Java class and a native library. Instead of having the JVM make direct calls to native methods, the JVM uses a pointer to the JNI to make the actual calls. This way, even if the JVM implementations are different, the layer they use to access the native methods (the JNI) is always the same.
There could not have been an easier way to make Java methods native. Here is a summary of the required steps:
For example, assume the following method exists in a Java class:
public void nativeMethod () { //the method's body }
This is how the method becomes native:
public native void nativeMethod ();
Now that you've declared the method to be native, where is its actual implementation? The method's implementation will be included in a native library. It is the duty of the class in which this method is a member of, to invoke the library, so that its implementation becomes available to whoever needs it. The easiest way to have the class invoke the library is to add the following to the class:
static { System.loadLibrary (nameOfLibrary); }
A static code block is always executed once when the class is first loaded. You can include virtually anything in a static code block; however, loading libraries is the most common use for it. If, for some reason, the library fails to load, an UnsatisfiedLineError exception will be thrown once a method from that library is called. If the library loads fine, the JVM will add the correct extension to its name (.dll in Windows, and .so in UNIX).
The JDK supplies a tool called javah, which is used to generate C header files for Java classes. The following is the general syntax for using javah:
javah [options] className
className
represents the name of the class (without the .class extension) you want to generate a C header file for. You can specify more than one class at the command line. For each class, javah adds a .h file to the classes' directory, by default. If you want the .h files placed elsewhere, use the -o option. If a class is in a package, you must specify the package along with the class name.If, for example, you want to generate a header file for the class myClass in the package myPackage, do the following:
javah myPackage.myClass
The generated header file will include the package name, (myPackage_myClass.h).
Here's a list of some of the options used with javah:
Option |
Description |
-jni |
Creates a JNI header file |
-verbose |
Displays progress information |
-version |
Displays the version of javah |
-o directoryName |
Outputs the .h file in specified directory |
-classpath path |
Overrides the default class path |
The contents of the .h file generated by javah include all the function prototypes for the native methods in the class. The prototypes are modified to allow the Java run-time system to find and invoke the native methods. This modification basically involves changing the name of the method according to a naming convention established for native method invocation. The modified name includes the prefix Java_ to the class and method names. So, if you have a native method called nativeMethod in a class called, myClass, the name that appears in the myClass.h file is Java_myClass_nativeMethod.
What was covered in this chapter: