Previous | Next | Trail Map | Using the JNI | Java Native Interface Programming

Declaring Native Methods

This lesson illustrates how to declare a native method in the Java programming language and how to generate the corresponding C/C++ language function prototype.

The Java Side

Our first example, Prompt.java, contains a native method that accepts and prints a Java programming language string. The program calls the native method, which waits for user input and then returns the line the user typed in.

The Prompt class contains a main method which is used to invoke the program. In addition, there is a getLine native method:

private native String getLine(String prompt);

Notice that the declarations for native methods are almost identical to the declarations for regular, non-native Java programming language methods. There are two differences. First, native methods must have the native keyword. The native keyword informs the Java programming language compiler that the implementation for this method is provided in another language. Secondly, the native method declaration is terminated with a semicolon (the statement terminator symbol) because there are no implementations for native methods in the Java programming language class file.

The Native Language Side

You must declare and implement native methods in a native language, such as C or C++. Before you do this, it is helpful to generate the header file that contains the function prototype for the native method implementation.

Compile the Prompt.java file and then generate the .h file. First, compile the Prompt.java file as follows:

javac Prompt.java

Once you have successfully compiled Prompt.java and have created the Prompt.class file, you can generate a JNI-style header file by specifying a -jni option to javah:

javah -jni Prompt

Examine the Prompt.h file. Note the function prototype for the native method getLine that you declared in Prompt.java.

JNIEXPORT jstring JNICALL 
Java_Prompt_getLine(JNIEnv *, jobject, jstring);

The native method function definition in the implementation code must match the generated function prototype in the header file. Always include JNIEXPORT and JNICALL in your native method function prototypes. JNIEXPORT and JNICALL ensure that the source code compiles on platforms such as Win32 that require special keywords for functions exported from dynamic link libraries.

Native method names are concatenated from the following components:

Graphically, this looks as follows:


Note: Overloaded native method names, in addition to the above components, have an extra two underscores "__" appended to the method name followed by the argument signature.

Thus, the native code implementation for the Prompt.getLine method becomes Java_Prompt_getLine. (There is no package name component because the Prompt class is in the default package.)

Each native method has two parameters in addition to those parameters that you declared on the Java programming language side. The first parameter, JNIEnv *, is the JNI interface pointer. This interface pointer is organized as a function table, with every JNI function at a known table entry point. Your native method invokes specific JNI functions to access Java objects through the JNIEnv * pointer. The jobject parameter is a reference to the object itself (it is like the this pointer in C++).

Lastly, notice that the JNI has a set of type names, such as jobject and jstring, and each type corresponds to Java programming language types. This is covered in the next section.


Previous | Next | Trail Map | Using the JNI | Java Native Interface Programming