這裏主要講述在LINUX(Ubuntu 10.04)下通過JNI調用底層.c文件中的函數
以最簡單的“Hello”舉例
第一步:
寫一個JniTest.java文件,內容如下
public class JniTest
{
static
{
System.loadLibrary("Hello");
}
public native void output();
public static void main(String[] args)
{
System.out.println(System.getProperty("java.library.path"));
JniTest test = new JniTest();
test.output();
}
}
使用javac編譯.java文件
再使用javah -jni JniTest會生成一個JniTest.h的頭文件,內容如下
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JniTest */
#ifndef _Included_JniTest
#define _Included_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JniTest
* Method: output
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JniTest_output
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
注意:
1.public native void output(),這個方法可以看作接口中的一個方法,只不過是由外部的其他語言(這裏是C)來實現這個方法。
2.靜態塊裏的System.loadLibrary(String s)方法是根據字符串s,去java.library裏去加載名爲"lib" + s + ".so"的動態庫文件(Windows下爲dll).
這樣就可以訪問native方法了。
3.可以通過System.out.println(System.getProperty("java.library.path"));來獲取java.library的具體路徑,後面要用到。
第二步:
根據JniTest.h頭文件,編寫jni_test.c文件實現相應的方法
#include <stdio.h>
#include "JniTest.h"
#include <jni.h>
JNIEXPORT void JNICALL Java_JniTest_output(JNIEnv * jnienv, jobject job)
{
printf("Hello,ZYC!/n");
}
然後在SHELL下將其編譯成動態鏈接庫
$gcc -shared -I /usr/lib/jvm/java-6-sun-1.6.0.22/include/ -I /usr/lib/jvm/java-6-sun-1.6.0.22/include/linux/ -I /usr/include/ jni_test.c -o libHello.so
gcc參數解釋(可以通過man gcc查看)
-shared 該選項指定生成動態連接庫,不用該標誌外部程序無法連接。相當於一個可執行文件
-I 包含路徑,這裏/usr/lib/jvm/java-6-sun-1.6.0.20/include下包含的jni.h,/usr/lib/jvm/java-6-sun-1.6.0.20/include/linux下包含的是jni-mid.h,/usr/include/包含用戶的.h文件
-o file 將內容寫入file中,這裏寫入libHello.so
然後就會生成libHello.so這個文件。
第三步:
執行方法:
1.單次執行時候指定library位置
java -Djava.library.path=. JniTest
2.將通過java library來執行
$sudo cp libHello.so /usr/lib/jvm/java-6-sun-1.6.0.22/jre/lib/i386/client/
後面的路徑就是通過System.out.println(System.getProperty("java.library.path"))獲取到的
然後java JniTest即可看到結果,亦可以在eclipse下使用
輸出結果:
dane-zhu@dane-zhu-desktop:~/workspace/JavaJni/src$ java JniTest
/usr/lib/jvm/java-6-sun-1.6.0.22/jre/lib/i386/client:/usr/lib/jvm/java-6-sun-1.6.0.22/jre/lib/i386:/usr/lib/jvm/java-6-sun-1.6.0.22/jre/../lib/i386:.:.:.::/usr/java/packages/lib/i386:/lib:/usr/lib
Hello,ZYC!
That'OK!