/* 08/31/04 PDM - A quick and dirty set of instructions for making JNI work for the CS290 RSA/AES assignment. */ First, note that there are good online tutorials for using JNI. This is just a minimal set of instructions to make JNI work for this particular project. One tutorial is provided by Sun and is located at: http://java.sun.com/docs/books/tutorial/native1.1/index.html These instructions assume that there is code provided to perform the actual AES encryption/decryption in the form of a callable C library. The library header file is named aes.h and the C library is named aes.o. 1. Create the java class that will be a wrapper for the native code. This class shall henceforth be referred to as the "Java wrapper class". A sample template is provided in AESWrapper.java, (pointed to next to this file in the assignment html page), but students are encouraged to develop their own interfaces should they so desire. One word of caution: for simplicitie's sake, it is probably easiest to stick to "basic types" for the signatures of the interface functions (i.e. int, byte, byte[], etc.) 2. Compile the Java wrapper class developed in step 1. For the template provided, the following command will suffice. > javac AESWrapper.java 3. Create the native C header file using 'javah'. This will generate a C header file that will be compiled into a shared library in a later step. For the compiled template class, this can be accomplished with the following command. > javah AESWrapper The path to the .class file must be in the classpath. Note that the native functions defined in the java wrapper class have corresponding methods in the generated header file. They have some additional parameters, whose purpose and meaning can be divined from the tutorial mentioned above. In short, they provide hooks so that the C code can communicate with the JRE. For the simple interface defined in AESWrapper.java, the only additional parameter of interest is the JNIEnv* which will be mentioned in the next step. 4. Create the C implementation of the interface generated by 'javah' in step 3. For the interface generated by using AESWrapper.java, this should be a relatively simple task. There are few methods on the JNIEnv* parameter that are necessary for array access/modification. GetArrayLength, GetByteArrayElements, ReleaseByteArrayElements are shown in use below and at the Sun java tutorial at: http://java.sun.com/docs/books/tutorial/native1.1/implementing/array.html JNIEXPORT jint JNICALL Java_AESWrapper_aes_1init (JNIEnv *env, jobject obj, jbyteArray array, jint len) { /* Get the length of the array and a local copy of the data */ jsize arrayLen = (*env)->GetArrayLength(env, array); jbyte *bytes = (*env)->GetByteArrayElements(env, array, 0); /* some manipulation of the data in 'bytes' variable. A jbyte is equivalent to byte. Other mappings are described at: http://java.sun.com/docs/books/tutorial/native1.1/integrating/types.html */ /* reclaim memory and update JRE with changes to 'bytes' */ (*env)->ReleaseByteArrayElements(env, array, bytes, 0); return 0; } 5. Compile the C implementation into a shared library. The resulting shared library should be placed somewhere in the LD_LIBRARY_PATH. Alternatively, its location can be specified on the java command line. Assuming that the C file implemented in step 4 is called aes-interface.c, it can be compiled and linked with the aes code with the following commands to yield libaes.so: > gcc -c -I/usr/local/java/include -I/usr/local/java/include/solaris aes-interface.c > ld -o libaes.so -shared aes.o aes-interface.o 6. Run a java program that makes use of the java wrapper class. The template AESWrapper has a main() method that can be run to test the encryption/decryption. > java AESWrapper "this is a test sentence" OR > java -Djava.library.path= AESWrapper An UnsatisfiedLinkError may be raised during the program execution. This indicates that the shared library compiled in step 5 was not found by the JRE. In this case, check the following: - Is the shared library should be located in LD_LIBRARY_PATH? - Does the shared library have the correct name? If the java wrapper class has a System.loadLibrary("aes") function call then the libary should be named "libaes.so" - Try specifying the location of the library in the command line: > java -Djava.library.path= AESWrapper