用JNI實現
執行個體:
建立HelloWorld.java
class HelloWorld
{
private native void print();
public staticvoid main(String[] args)
{
new HelloWorld().print();
}
static
{
System.loadLibrary("HelloWorld");
}
}
注意print方法的聲明,關鍵字native表明該方法是一個原生代碼實現的。另外注意static程式碼片段的System.loadLibrary調用,這段代碼錶示在程式載入的時候,自動載入libHelloWorld.so庫。
編譯HelloWorld.java
在命令列中運行如下命令:
javac HelloWorld.java
在當前檔案夾編譯產生HelloWorld.class。
產生HelloWorld.h
在命令列中運行如下命令:
javah -jni HelloWorld
在當前檔案夾中會產生HelloWorld.h。開啟HelloWorld.h將會發現如下代碼:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
該檔案中包含了一個函數Java_HelloWorld_print的聲明。這裡麵包含兩個參數,非常重要,後面講實現的時候會講到。
實現HelloWorld.c
建立HelloWorld.c檔案輸入如下的代碼:
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
}
注意必須要包含jni.h標頭檔,該檔案中定義了JNI用到的各種類型,宏定義等。
另外需要注意Java_HelloWorld_print的兩個參數,本例比較簡單,不需要用到這兩個參數。但是這兩個參數在JNI中非常重要。
env代表java虛擬機器環境,Java傳過來的參數和c有很大的不同,需要調用JVM提供的介面來轉換成C類型的,就是通過調用env方法來完成轉換的。
obj代表調用的對象,相當於c++的this。當c函數需要改變調用對象成員變數時,可以通過操作這個對象來完成。
編譯產生libHelloWorld.so
在Linux下執行如下命令來完成編譯工作:
cc -I/usr/lib/jvm/java-6-sun/include/linux/
-I/usr/lib/jvm/java-6-sun/include/
-fPIC -shared -o libHelloWorld.so HelloWorld.c
或者(我是這樣編譯的)
gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared -o libHelloWorld.so HelloWorld.c
在目前的目錄產生libHelloWorld.so。注意一定需要包含Java的include目錄(請根據自己系統內容設定),因為Helloworld.c中包含了jni.h。
另外一個值得注意的是在HelloWorld.java中我們LoadLibrary方法載入的是
“HelloWorld”,可我們產生的Library卻是libHelloWorld。這是Linux的連結規定的,一個庫的必須要是:lib+庫
名+.so。連結的時候只需要提供庫名就可以了。
運行Java程式HelloWorld
大功告成最後一步,驗證前面的成果的時刻到了:
java HelloWorld
如果你這步發生問題,如果這步你收到java.lang.UnsatisfiedLinkError異常,可以通過如下方式指明共用庫的路徑:
java -Djava.library.path='.' HelloWorld
當然還有其他的方式可以指明路徑請參考《在Linux平台下使用JNI》。
我們可以看到久違的“Hello world!”輸出了。