Thursday, December 8, 2011

My JNI Experiments Part I | Handling integers

JNI(Java Native Interface) is a very important aspect of Java programming language. JNI provides an interface to the native environment. So we can execute native methods within our Java programs. Lets assume that we  have to do a task that need high performance in our Java program. C/C++ is good for high performance tasks rather than Java. If we can cooperate or embed C/C++ with our Java code, we can achieve our high performance targets. But Java is interpreted(byte code based) and C/C++ is compiled. So JNI is the way to cooperate those native code with our Java code.

Lets assume we have calculate factorial of a given integer value. calculation is done by a code written in C++. We call the C++ native method within our Java program and show the result on the console.


Step 1 : write Java code
OurProgram.java
This Java program contains the main method
   1 public class OurProgram{
   2         public static void main(String args[]){
   3                 try{
   4                         System.loadLibrary("myfactorialdll");
   5                         JNICallerInt jnic=new JNICallerInt();
   6                         
   7                         for(int i=1;i<15;i++){
   8                                 int factorial=jnic.factorial(i);
   9                                 System.out.println("Factorial of " + i + " is \t : " + factorial);
  10                         }
  11                         
  12                 }catch(UnsatisfiedLinkError e){
  13                         System.out.println("Unsatisfied link to the dll");
  14                 }
  15         }
  16 }

JNICallerInt.java
create a interface to the C++ method
   1 class JNICallerInt{
   2         public native int factorial(int value);
   3 }



Step 2 : Compile Java program
javac OurProgram.java

Step 3 : Generate header files
we use javah command.
javah JNICallerInt
 because JNICallerInt class contains the interface for the native method.

then javah command generate the required header file(JNICallerInt.h)  now we have to implement the required C++ or C method.
lets have a look at the generated header file

JNICallerInt.h

   1 /* DO NOT EDIT THIS FILE - it is machine generated */
   2 #include <jni.h>
   3 /* Header for class JNICallerInt */
   4 
   5 #ifndef _Included_JNICallerInt
   6 #define _Included_JNICallerInt
   7 #ifdef __cplusplus
   8 extern "C" {
   9 #endif
  10 /*
  11  * Class:     JNICallerInt
  12  * Method:    factorial
  13  * Signature: (I)I
  14  */
  15 JNIEXPORT jint JNICALL Java_JNICallerInt_factorial
  16   (JNIEnv *, jobject, jint);
  17 
  18 #ifdef __cplusplus
  19 }
  20 #endif
  21 #endif

now we have to implement the generated function prototype. in our C++ code. lets have a look at the C++ implementation of this header file

FactorialDll.cpp

   1 #include "JNICallerInt.h"
   2 
   3 int factorial(int val);
   4 
   5 JNIEXPORT jint JNICALL Java_JNICallerInt_factorial
   6   (JNIEnv *env, jobject obj, jint value){
   7         int factorialVal=factorial(value);
   8         return factorialVal;
   9   }
  10   
  11 int factorial(int val){
  12         if(val<1){
  13                 return 1;
  14         }else{
  15                 return val*factorial(val-1);
  16         }
  17 }
  18 

in this method we have given appropriate parameter names for the generated function prototype. and then we have written a recursive method to calculate the factorial of the  given number.

Step 4 :compile C++ code
To compile a C++ code there are plenty of free compilers. I tried with MinGw and dmc compilers but they didn't work for me. So I tried with Visual C++ compiler coming as a part of the Microsoft Visual Studio it works well. I saw there are some ways to use above dmc and MinGw with JNI but I didn't tried those techniques.

cl -IC:\Java\jdk1.7.0\include\win32 -IC:\Java\jdk1.7.0\include -LD FactorialDll.cpp -Femyfactorialdll.dll

If we are going to do this compilation in linux environment we can use cc, gcc, g++ compilers.

When we compile the C++ code we must show the relevant paths to the C/C++ compilers because the header file includes "jni.h" file. The relevant paths can be showed using -I option. Give it according to your JDK installation.

<path to JDK>\include

<path to JDK>\include\win32

The dll file will be generated by the compiler If you have successfully written the code.

the dll file must be named with the loaded library name in our Java code
System.loadLibrary("myfactorialdll");


remember that we don't mention the extension dll or so in the java code. we mention only the name.

Step 4 : Run the program :)

java OurProgram

Deploying:
we need only the dll file and other relevant class to deploy our program.
Drawbacks:
There is a portability issue. We have to re compile the C++ code if we want to deploy the application on another platform. 
download source codes 

0 comments:

Post a Comment

© kani.stack.notez 2012 | Blogger Template by Enny Law - Ngetik Dot Com - Nulis