Changes between Version 16 and Version 17 of Traffic:


Ignore:
Timestamp:
Jan 19, 2010, 6:33:07 PM (14 years ago)
Author:
stefan.nour
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Traffic:

    v16 v17  
    2828== Implementation ==
    2929We tried to integrate the parallelized algorithm into the existing framework by calling a C program from a java context.
    30 [http://java.sun.com/docs/books/jni/html/start.html#26346]
     30Figure below illustrates the process for using JDK or Java 2 SDK releases to write a simple Java application that calls a C function to print "Hello World!". The process consists of the following steps:
     31
     32   1. Create a class (HelloWorld.java) that declares the native method.
     33   2. Use javac to compile the HelloWorld source file, resulting in the class file HelloWorld.class. The javac compiler is supplied with JDK or Java 2 SDK releases.
     34   3. Use javah -jni to generate a C header file (HelloWorld.h) containing the function prototype for the native method implementation. The javah tool is provided with JDK or Java 2 SDK releases.
     35   4. Write the C implementation (HelloWorld.c) of the native method.
     36   5. Compile the C implementation into a native library, creating Hello-World.dll . Use the C compiler and linker available on the host environment.
     37   6. Run the HelloWorld program using the java runtime interpreter. Both the class file (HelloWorld.class) and the native library (HelloWorld.dll) are loaded at runtime.
     38Here is an example of how this works:
     39
     40[[Image(callCProgramFromJava.gif)]]
     41
     42=== Declare the Native Method ===
     43
     44You begin by writing the following program in the Java programming language. The program defines a class named HelloWorld that contains a native method, print.
     45
     46 class HelloWorld {
     47     private native void print();
     48     public static void main(String[] args) {
     49         new HelloWorld().print();
     50     }
     51     static {
     52         System.loadLibrary("HelloWorld");
     53     }
     54 }
     55
     56The HelloWorld class definition begins with the declaration of the print native method. This is followed by a main method that instantiates the Hello-World class and invokes the print native method for this instance. The last part of the class definition is a static initializer that loads the native library containing the implementation of the print native method.
     57
     58There are two differences between the declaration of a native method such as print and the declaration of regular methods in the Java programming language. A native method declaration must contain the native modifier. The native modifier indicates that this method is implemented in another language. Also, the native method declaration is terminated with a semicolon, the statement terminator symbol, because there is no implementation for native methods in the class itself. We will implement the print method in a separate C file.
     59
     60Before the native method print can be called, the native library that implements print must be loaded. In this case, we load the native library in the static initializer of the HelloWorld class. The Java virtual machine automatically runs the static initializer before invoking any methods in the HelloWorld class, thus ensuring that the native library is loaded before the print native method is called.
     61
     62We define a main method to be able to run the HelloWorld class. Hello-World.main calls the native method print in the same manner as it would call a regular method.
     63
     64System.loadLibrary takes a library name, locates a native library that corresponds to that name, and loads the native library into the application. We will discuss the exact loading process later in the book. For now simply remember that in order for System.loadLibrary("HelloWorld") to succeed, we need to create a native library called HelloWorld.dll on Win32.
     65=== Compile the HelloWorld Class ===
     66
     67After you have defined the HelloWorld class, save the source code in a file called HelloWorld.java. Then compile the source file using the javac compiler that comes with the JDK or Java 2 SDK release:
     68
     69 javac HelloWorld.java
     70
     71This command will generate a HelloWorld.class file in the current directory.
     72
     73=== Create the Native Method Header File ===
     74
     75Next we will use the javah tool to generate a JNI-style header file that is useful when implementing the native method in C. You can run javah on the Hello-World class as follows:
     76
     77 javah -jni HelloWorld
     78
     79The name of the header file is the class name with a ".h" appended to the end of it. The command shown above generates a file named HelloWorld.h. We will not list the generated header file in its entirety here. The most important part of the header file is the function prototype for Java_HelloWorld_print, which is the C function that implements the HelloWorld.print method:
     80
     81 JNIEXPORT void JNICALL
     82 Java_HelloWorld_print (JNIEnv *, jobject);
     83
     84Ignore the JNIEXPORT and JNICALL macros for now. You may have noticed that the C implementation of the native method accepts two arguments even though the corresponding declaration of the native method accepts no arguments. The first argument for every native method implementation is a JNIEnv interface pointer. The second argument is a reference to the HelloWorld object itself (sort of like the "this" pointer in C++).
     85
     86=== Write the Native Method Implementation ===
     87
     88The JNI-style header file generated by javah helps you to write C or C++ implementations for the native method. The function that you write must follow the -prototype specified in the generated header file. You can implement the Hello-World.print method in a C file HelloWorld.c as follows:
     89
     90 #include <jni.h>
     91 #include <stdio.h>
     92 #include "HelloWorld.h"
     93 
     94 JNIEXPORT void JNICALL
     95 Java_HelloWorld_print(JNIEnv *env, jobject obj)
     96 {
     97     printf("Hello World!\n");
     98     return;
     99 }
     100
     101The implementation of this native method is straightforward. It uses the printf function to display the string "Hello World!" and then returns. As mentioned before, both arguments, the JNIEnv pointer and the reference to the object, are ignored.
     102
     103The C program includes three header files:
     104
     105    * jni.h -- This header file provides information the native code needs to call JNI functions. When writing native methods, you must always include this file in your C or C++ source files.
     106    * stdio.h -- The code snippet above also includes stdio.h because it uses the printf function.
     107    * HelloWorld.h -- The header file that you generated using javah. It includes the C/C++ prototype for the Java_HelloWorld_print function. 
     108
     109=== Compile the C Source and Create a Native Library ===
     110
     111Remember that when you created the HelloWorld class in the HelloWorld.java file, you included a line of code that loaded a native library into the program:
     112
     113 System.loadLibrary("HelloWorld");
     114 
     115
     116Now that all the necessary C code is written, you need to compile Hello-World.c and build this native library.
     117
     118Different operating systems support different ways to build native libraries. On Win32, the following command builds a dynamic link library (DLL) HelloWorld.dll using the Microsoft Visual C++ compiler:
     119
     120 cl -Ic:\java\include -Ic:\java\include\win32
     121     -MD -LD HelloWorld.c -FeHelloWorld.dll
     122
     123The -MD option ensures that HelloWorld.dll is linked with the Win32 multithreaded C library. The -LD option instructs the C compiler to generate a DLL instead of a regular Win32 executable. Of course, on both Solaris and Win32 you need to put in the include paths that reflect the setup on your own machine.
     124
     125===  Run the Program ===
     126
     127At this point, you have the two components ready to run the program. The class file (HelloWorld.class) calls a native method, and the native library (Hello-World.dll) implements the native method.
     128
     129Because the HelloWorld class contains its own main method, you can run the program on Solaris or Win32 as follows:
     130
     131 java HelloWorld
     132
     133You should see the following output:
     134
     135 Hello World!
     136
     137It is important to set your native library path correctly for your program to run. The native library path is a list of directories that the Java virtual machine searches when loading native libraries. If you do not have a native library path set up correctly, then you see an error similar to the following:
     138
     139 java.lang.UnsatisfiedLinkError: no HelloWorld in library path
     140         at java.lang.Runtime.loadLibrary(Runtime.java)
     141         at java.lang.System.loadLibrary(System.java)
     142         at HelloWorld.main(HelloWorld.java)
     143
     144Make sure that the native library resides in one of the directories in the native library path. If you are running on a Windows 95 or Windows NT machine, make sure that HelloWorld.dll is in the current directory, or in a directory that is listed in the PATH environment variable.
     145
     146In Java 2 SDK 1.2 release, you can also specify the native library path on the java command line as a system property as follows:
     147
     148 java -Djava.library.path=. HelloWorld
     149
     150The "-D" command-line option sets a Java platform system property. Setting the java.library.path property to "." instructs the Java virtual machine to search for native libraries in the current directory.
     151
    31152
    32153== Experimental Results ==