JNI全名是Java Native Interface,通過JNI技術可以實現Java和其他編程語言的互相調用。這裏我們使用的是Java和C的互相調用,Java提供本地接口,C實現該本地接口。
我使用的是RHEL 5,主要是為了測試壹下在Linux平臺下,了解JNI技術是如何實現的。通過壹個HelloWorld實例,具體過程在下面講解。
首先,實現的是Java本地接口Hello.java,代碼如下所示:
class?HelloWorld?{public?native?void?sayHello();
static?{
System.loadLibrary("HelloWorld");
}
public?static?void?main(String[]?args)?{
(new?HelloWorld()).sayHello();
}
}
其中,方法聲明為native,其實HelloWorld類就相當於壹個接口,是為其他編程語言聲明的接口。System.loadLibrary("HelloWorld");語句是壹個static塊,也就是在該HelloWorld類加載的時候進行執行。其中,該語句實現了加載本地的動態連接庫(DLL),在Linux平臺下,動態連接庫文件是以.so作為擴展名的,也就是標準對象(Standard Object)。
對該本地接口類進行編譯:
[root@localhost jni]# javac HelloWorld.java
接著,通過編譯的HelloWorld.class文件,生成C語言的頭文件,執行命令:
[root@localhost jni]# javah -jni HelloWorld
可以看到,在當前目錄下生成壹個HelloWorld.h文件,該文件就是C的接口文件,為使用C實現Java接口中定義的方法,可以發現在HelloWorld.h中有壹個方法聲明:
#ifndef?__HelloWorld__#define?__HelloWorld__
#include?<jni.h>
#ifdef?__cplusplus
extern?"C"
{
#endif
JNIEXPORT?void?JNICALL?Java_HelloWorld_sayHello?(JNIEnv?*env,?jobject);
#ifdef?__cplusplus
}
#endif
#endif?/*?__HelloWorld__?*/
然後,用C實現該方法,在HelloWorld.c文件中,代碼如下:
#include?<jni.h>#include?"HelloWorld.h"
#include?<stdio.h>
JNIEXPORT?void?JNICALL?Java_HelloWorld_sayHello?(JNIEnv?*env,?jobject?obj)?{
printf("Hello,the?World!!!");
}
這裏,方法簽名為Java_HelloWorld_sayHello (JNIEnv *env, jobject obj),添加了形參obj,否則無法通過編譯。
接下來,生成動態連接庫libHelloWorld.so,執行命令:
[root@localhost jni]# gcc -fPIC -shared -o libHelloWorld.so HelloWorld.c
可以在當前目錄下看到libHelloWorld.so,動態連接庫文件名稱以lib開頭。將該文件拷貝到usr/lib目錄下面,就可以測試了。
現在執行如下命令進行測試:
[root@localhost jni]# java HelloWorld
輸出如下:
Hello,the World!!!
這只是壹個非常簡單的例子,主要是了解JNI在Linux下該如何用。在實際應用中,可能會非常復雜,並且要記住,壹旦使用了JNI技術,系統的可移植性被破壞了。有些應用中,正是基於這種特性實現,比如限制軟件的傳播使用,保護開發商權益,等等。