A Quick Review | |
public class HelloWorld { public native void displayHelloWorld(); static{ System.loadLibrary("hello"); } public static void main(String[] args) { new HelloWorld().displayHelloWorld(); } } Actually getting this all working can be tricky. create header file: javah HelloWorld C program: #include <jni.h> #include "HelloWorld.h" #include <stdio.h> JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv* env, jobject obj) { printf("Hello world!\n"); return; }Compile C program (include paths are for CS machines): gcc -I/usr/local/pkg/jdk/current/include/ -I/usr/local/pkg/jdk/current/include/linux hello.c -c -o hello.o ld -G hello.o -o libhello.so Run java program: java -Djava.library.path=./ HelloWorld If you set your library path to include the local directory, you don't need the -D option: export LD_LIBRARY_PATH=./ |
Working with Arrays | |
Suppose we had an array of integers, and we wanted to sum them in native code:
native int sumArray(int arr[]);We would have this native code: JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv* env, jobject obj, jintArray arr); { //Get Length of Array jsize len = (*env)->GetArrayLength(env, arr); int i, sum=0; //Get pointer to the array of primitive Java objects jint* body = (*env)->GetIntArrayElements(env,arr,0); for(i=0; i<len, i++) { sum += body[i]; } //Tell Java we're done with the array. (This is important for the GC) (*env)->ReleaseIntArrayElements(env,arr,body,0); return sum; } |
Exercise |
|
A common usage of JNI is to use native code for the CPU intensive part of the application. Write two program, one a Java program to multiply two 3x3 matrices, and a Java program that does the same thing with a native method. The signature of the Java method should be multiplyMatrices(int[] a, int[] b, int[] result). Here's a simple C program that multiplies two 3x3 matrices for your reference: det.c. Time the two programs. Which is faster? Is the overhead of transitioning to native code worth the speed-up of the multiply? What about for 4x4 matrices? |