Sunday, December 9, 2012

Learning JNI(一):

one good webpage:
http://marakana.com/bookshelf/java_fundamentals_tutorial/_java_native_interface_jni.html


I'm using eclipse.
So first I need to add javah for eclipse.

run -> external tools - > external tools configuarations -> Program.
Add Name:javah_JNI_gen
Location: /usr/lib/jvm/java-1.6.0-openjdk/bin/javah
Working Directory:
${workspace_loc:/${project_name}/bin}
Arguments:
-classpath ${project_classpath} -v -d ${workspace_loc:/${project_name}/src} ${java_type_name}


Then write some java code, such as:


package simple;

public class Hello {

    public native void sayHi(String who, int times); //1

      static { System.loadLibrary("HelloImpl"); } //2

      public static void main (String[] args) {
        Hello hello = new Hello();
        hello.sayHi("Ying", 2); //3
      }

}


Choose Run -> external tools -> javah***, then it will create a file simple_Hello.h in bin/

Now you can write a simple_Hello.c

#include <stdio.h>
#include "simple_Hello.h"

JNIEXPORT void JNICALL Java_simple_Hello_sayHi(JNIEnv *env, jobject obj, jstring who, jint times) {
  jint i;
  jboolean iscopy;
  const char *name;
  name = (*env)->GetStringUTFChars(env, who, &iscopy);
  for (i = 0; i < times; i++) {
    printf("Hello %s\n", name);
  }
}

compile:

gcc -o libHelloImpl.so -lc -shared \
    -I/usr/lib/jvm/java-6-openjdk/include \
    -I/usr/lib/jvm/java-6-openjdk/include/linux simple_Hello.c  -fPIC

Note that in my case, nod adding -fPIC will have compile mistakes.

Now you can run the java program :)



When you use the *.so file for other project, add it into eclipse  Project -> Properties -> Libraries -> choose the bottom JRE System Library,

native library location -> Edit, add the path of the so file, such as:
/home/ying/study/tools/SVM-Light-1.5-to-be-released/jniLib




How to Load a Java Native/Shared Library (.so)

from http://www.chilkatsoft.com/java-loadLibrary-Linux.asp

There are several ways to make it possible for the Java runtime to find and load a native shared library (.so) at runtime. I will list them briefly here, followed by examples with more explanation below.
  1. Call System.load to load the .so from an explicitly specified absolute path.
  2. Copy the shared library to one of the paths already listed in java.library.path
  3. Modify the LD_LIBRARY_PATH environment variable to include the directory where the shared library is located.
  4. Specify the java.library.path on the command line by using the -D option.

1. Call System.load to load the shared library from an explicitly specified absolute path.

This choice removes all uncertainty, but embeds a hard-coded path within your Java application. Example:
import com.chilkatsoft.CkZip;

public class Test {
 
  static {
    try {
     System.load("/home/joe/chilkatJava/libchilkat.so");
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load.\n" + e);
      System.exit(1);
    }
  }

  public static void main(String argv[]) 
  {
    CkZip zip = new CkZip();
    System.out.println(zip.version());    
  }
}

2. Copy the shared library to one of the paths already listed in java.library.path

To view the paths listed in java.library.path, run this Java code:
String property = System.getProperty("java.library.path");
StringTokenizer parser = new StringTokenizer(property, ";");
while (parser.hasMoreTokens()) {
    System.err.println(parser.nextToken());
    }
Note: The java.library.path is initialized from the LD_LIBRARY_PATH environment variable.
The loadLibrary method may be used when the directory containing the shared library is in java.library.path. To load "libchilkat.so", call System.loadLibrary("chilkat"), as shown below.
import com.chilkatsoft.CkZip;

public class Test {
 
  static {
    try {
     
     System.loadLibrary("chilkat");
     
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load.\n" + e);
      System.exit(1);
    }
  }
 
  public static void main(String argv[])
   {
    CkZip zip = new CkZip();
    System.out.println(zip.version());
 }
  }

3. Modify the LD_LIBRARY_PATH environment variable to include the path where the Chilkat shared library is located.

For Bourne Shell, K Shell or Bash, type:
export LD_LIBRARY_PATH=/home/joe/chilkatJava-9.1.1-x86_64-linux:$LD_LIBRARY_PATH
For C Shell, type:
setenv LD_LIBRARY_PATH "/home/joe/chilkatJava-9.1.1-x86_64-linux:$LD_LIBRARY_PATH"

4. Specify the java.library.path on the command line by using the -D option.

For example:
java -Djava.library.path=".:/home/joe/chilkatJava-9.1.1-x86_64-linux" TestApp

No comments:

Post a Comment