1.native關鍵詞的引入
再完美的編程語言也有自己的不足之處,當然Java也不例外,Java的不足之處除了體現在運行速度(這點往往被一些其他編程語言使用者所詬病)上要比傳統的C++慢許多之外,Java無法直接訪問到操作系統底層(如系統硬件等),為此Java使用native(原生的)關鍵詞來擴展Java程序的功能。native關鍵字說明其修飾的方法是一個原生態方法,方法對應的實現不是在當前文件,而是在用其他語言(如C和C++)實現的文件中。Java語言本身不能對操作系統底層進行訪問和操作,但是可以通過JNI接口調用其他語言來實現對底層的訪問。JNI是Java Native Interface的縮寫,它提供了若干的API實現了Java和其他語言的通信(主要C&C++)。從Java1.1開始,JNI標准成為java平台的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI一開始是為了本地已編譯語言,尤其是C和C++而設計的,但是它並不妨礙你使用其他編程語言,只要調用約定受支持就可以了。使用java與本地已編譯的代碼交互,通常會喪失平台可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的。例如,使用一些舊的庫,與硬件、操作系統進行交互,或者為了提高程序的性能。JNI標准至少要保證本地代碼能工作在任何Java 虛擬環境。簡而言之,JNI功能即為:Java和本地代碼間的雙向交互。JNI允許Java代碼使用以其他語言編寫的代碼和代碼庫。Invocation API(JNI的一部分)可以用來將Java虛擬機(JVM)嵌入到本機應用程序中,從而允許程序員從本機代碼內部調用Java代碼。
2.JNI的使用場合
3.JNI的書寫步驟
第一步:編寫帶有native聲明的方法的Java類
第二步:使用javac命令編譯編寫的Java類
第三步:使用java -jni 來生成后綴名為.h的頭文件
第四步:使用其他語言(C、C++)實現本地方法
第五步:將本地方法編寫的文件生成動態鏈接庫
第六步:運行程序
4.一個JNI的簡單應用例子(以HelloJNI為例子)
第一步:編寫帶有native聲明的方法的Java類
public class HelloJNI { public native void displayHelloJNI();//所有native關鍵詞修飾的都是對本地的聲明 static { System.loadLibrary("hello");//載入本地庫 } public static void main(String[] args) { new JNI().displayHelloJNI(); } }
聲明native方法:如果想將一個方法做為一個本地方法的話,那么就必須聲明該方法為native,並且不能實現。 Load動態庫:System.loadLibrary("hello");加載動態庫(可以這樣理解:方法 displayHelloJNI()沒有實現,但是在后續步驟中就直接使用了,所以必須在使用之前對它進行初始化),這里一般是以static塊進行加載的。同時需要注意的是System.loadLibrary()的參數“hello”是動態庫的名字。
第二步:使用javac命令編譯編寫的Java類
javac HelloJNI.java
注意:JDK環境變量的配置
第三步:使用java -jni 來生成后綴名為.h的頭文件( 生成擴展名為h的頭文件javah HelloJNI)
頭文件javah HelloJNI內容如下:
1 /*DO NOT EDI TTHIS FILE - it is mach inegenerated*/ 2 #include<jni.h> 3 /*Header for class HelloJNI*/ 4 5 #ifndef_Included_HelloJNI 6 #define_Included_HelloJNI 7 #ifdef__cplusplus 8 extern"C"{ 9 #endif 10 /* 11 *Class:HelloJNI 12 *Method:displayHelloJNI 13 *Signature:()V 14 */ 15 JNIEXPORTvoidJNICALL 16 Java_HelloJNI_displayHelloJNI(JNIEnv*,jobject); 17 18 #ifdef__cplusplus 19 } 20 #endif 21 #endif
注意:這個h文件相當於在java里面的接口,這里聲明了一個Java_HelloJNI_displayHelloJNI (JNIEnv *, jobject)方法,然后在本地方法里面實現這個方法,也就是說在編寫C/C++程序的時候所使用的方法名必須和這里的一致
第四步:使用其他語言(C、C++)實現本地方法(編寫本地方法實現和由javah命令生成的頭文件里面聲明的方法名相同的方法)
1 #include"jni.h" 2 #include"HelloJNI.h" 3 4 //#includeotherheaders 5 6 JNIEXPORT void JNICALL 7 Java_HelloJNI_displayHelloJNI(JNIEnv*env,jobject obj) 8 { 9 printf("HelloJNI!\n"); 10 return; 11 }
注意:代碼第一行需要將jni.h(該文件可以在%JAVA_HOME%/include文件夾下面找到)文件引入,因為在程序中的JNIEnv、 jobject等類型都是在該頭文件中定義的;另外在第2行需要將HelloJNI.h頭文件引入,然后保存為 HelloJNIImpl.c。
第五步:將本地方法編寫的文件生成動態鏈接庫
