初使JNI

来源:互联网 发布:淘宝香水的货源 编辑:程序博客网 时间:2024/06/06 17:33

author:lanhxg

original site:https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html

Environment:ubuntu12.04 64bit
ps:  有参考一个哥们的,这个哥们网址忘记了,如有问题可以pm我

 Use JNI with C

Step 1: Write a Java Class that uses C Codes - HelloJNI.java
1234567891011121314
public class HelloJNI {   static {      System.loadLibrary("HelloJNI"); // Load native library at runtime                                   // hello.dll (Windows) or libhello.so (Unixes)   }    // Declare a native method sayHello() that receives nothing and returns void   private native void sayHello();    // Test Driver   public static void main(String[] args) {      new HelloJNI().sayHello();  // invoke the native method   }}

The static initializer invokes System.loadLibrary() to load the native library "Hello" (which contains the native methodsayHello()) during the class loading. It will be mapped to "hello.dll" in Windows; or"libhello.so" in Unixes. This library shall be included in Java's library path (kept in Java system variablejava.library.path); otherwise, the program will throw aUnsatisfiedLinkError. You could include the library into Java Library's path via VM argument-Djava.library.path=path_to_lib.

Next, we declare the method sayHello() as a native instance method, via keywordnative, which denotes that this method is implemented in another language. A native method does not contain a body. ThesayHello() is contained in the native library loaded.

The main() method allocate an instance of HelloJNI and invoke the native methodsayHello().

Compile the "HelloJNI.java" into "HelloJNI.class".

> javac HelloJNI.java
Step 2: Create the C/C++ Header file - HelloJNI.h

Run javah utility on the class file to create a header file for C/C++ programs:

> javah HelloJNI

The output is HelloJNI.h as follows:

1234567891011121314151617181920
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloJNI */ #ifndef _Included_HelloJNI#define _Included_HelloJNI#ifdef __cplusplusextern "C" {#endif/* * Class:     HelloJNI * Method:    sayHello * Signature: ()V */JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *, jobject); #ifdef __cplusplus}#endif#endif

The header declares a C function Java_HelloJNI_sayHello as follows:

JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *, jobject);

The naming convention for C function is Java_{package_and_classname}_{function_name}(JNI arguments). The dot in package name shall be replaced by underscore.

The arguments:

  • JNIEnv*: reference to JNI environment, which lets you access all the JNI fucntions.

  • jobject: reference to "this" Java object.

We are not using these arguments in the hello-world example, but will be using them later. Ignore the macrosJNIEXPORT andJNICALL for the time being.

The extern "C" is recognized by C++ compiler only. It notifies the C++ compiler that these functions are to be compiled using C's function naming protocol (instead of C++ naming protocol). C and C++ have different function naming protocols as C++ support function overloading and uses a name mangling scheme to differentiate the overloaded functions. Read "Name Mangling".

Step 3: C Implementation - HelloJNI.c
123456789
#include <jni.h>#include <stdio.h>#include "HelloJNI.h" // Implementation of native method sayHello() of HelloJNI classJNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) {   printf("Hello World!\n");   return;}


Save the C program as "HelloJNI.c".

The header "jni.h" is available under the "<JAVA_HOME>\include" and "<JAVA_HOME>\include\win32" directories, where<JAVA_HOME> is your JDK installed directory (e.g., "c:\program files\java\jdk1.7.0").

The C function simply prints the message "Hello world!" to the console.

Compile the C program - this depends on the C compiler you used.

For Ubuntu :

> export export LD_LIBRARY_PATH=$PWD> gcc -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/linux -fPIC -shared -o libHelloJNI.so HelloJNI.c> java HelloJNI

You can do all steps as a shell:

#!/bin/sh JAVA_HOME=$(readlink -f /usr/bin/javac | sed "s:bin/javac::") #echo $JAVA_HOMEexport LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD echo $LD_LIBRARY_PATHsfile=$1append=javash_append=sosh_prefix=libjfile=${sfile}.${append}cfile=${sfile}.csharefile=${sh_prefix}${sfile}.${sh_append}javac $jfilejavah $sfile gcc -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/linux -fPIC -shared -o $sharefile $cfile java $sfile

Save above command in a shell file such as  "build.sh"

> chmod a+x build.sh> ./build.sh HelloJNI

0 0