InOnIt.com
Cygwin/Java
FAQ
Calling C from Java
Organizing for JNI
Writing the HelloWorld class
Creating a .h file
Writing the C function
Loading the DLL into the JVM
Running the program
Starting a JVM from C
MLS Playoff Odds
World Football Rankings & World Cup Odds
NCAA Basketball Ratings
Hearts
Personal Home Pages
David's Company

Creating a C Header File Using javah

In the last step, we created a Java file which simply declared a native method and compiled it. When the method is invoked at runtime, how will the virtual machine find it? How will it know what function to invoke?

JNI C function names are generated by mangling the Java method's name, declaring class, and signature in a way to make sure that every Java method has a distinct C function name. The javah tool (in the JDK's bin directory) will generate a C header file (.h) containing the necessary function prototype.

javah expects a Java class name as its argument, and will generate the C function prototypes for that class's native methods. On my machine, I'm making sure the header file ends up in the same directory as the Java source file (just to keep things simple), so the following command is executed from the directory in which HelloWorld.java is located. (Or I could change the value of the -o option below.) If you have a normal way of structuring C projects, feel free to substitute it here, altering the commands accordingly.

Let's run javah on HelloWorld and see what we get:

			javah -classpath [wherever you compiled HelloWorld] -o HelloWorld.h example.jni.HelloWorld
		


/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class example_jni_HelloWorld */

#ifndef _Included_example_jni_HelloWorld
#define _Included_example_jni_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     example_jni_HelloWorld
 * Method:    writeHelloWorldToStdout
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_example_jni_HelloWorld_writeHelloWorldToStdout
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

So there is our C function prototype. Note that the compiler has examined the Java native method's return type and decided our C function should be a void function (based on its Java return type). The VM will pass our native code two arguments:

  • a JNIEnv, which is an object which can be used to access JNI features, and
  • a jclass, representing the HelloWorld class.
If our native method were not static, the second argument would be a jobject representing the Java this reference, rather than the jclass.

The JNIEXPORT and JNICALL #defines are used to deal with Windows/UNIX differences in how functions are "exported" for use in shared libraries, and differences in calling conventions. You can look in jni_md.h (in the JDK's include/win32 directory) if you are interested. Note that the JNIEXPORT causes the function to be exported (roughly analogous to making a method public in Java) from the DLL.

We're ready to write the function's implementation.