JNI的簡單使用

Java通過JNI調用本地方法,而本地方法是以庫文件的形式存放的(在Windows平臺下是DLL文件形式,在UNIX機器上是SO文件形式)。通過調用本地的庫文件的內部方法,使Java可以實現和本地機器的緊密聯繫,調用系統級的各接口方法

使用的簡單流程:

一、Java中所需要做的工作

1、在Java程序中,首先需要在類中聲明所調用的庫名稱,如

[java] view plaincopy
  1. static {  
  2. System.loadLibrary(“testdll”);  
  3. }  

這裏庫的擴展名可以不用寫出來,究竟是DLL還是SO,由系統自己判斷

2、還需要對將要調用的方法做本地聲明,關鍵字爲native。且只需要聲明,而不需要具體實現

[java] view plaincopy
  1. public native static void set(int i);  
  2. public native static int get();  

得到的Java程序如下:TestJNI.java

[java] view plaincopy
  1. public class TestJNI {  
  2.     static {  
  3.         System.loadLibrary("testdll");  
  4.     }  
  5.     public native static int get();  
  6.     public native static void set(int i);  
  7.     public static void main(String[] args) {  
  8.         testdll test = new testdll();  
  9.         test.set(10);  
  10.         System.out.println(test.get());  
  11.     }  
  12. }  
3、使用javac TestJNI.java編譯它,得到TestJNI.class

再用javah TestJNI,則會在當前目錄下生成TestJNI.h文件

 注意:用javah命令生成相應h頭文件的時候有可能會出現無法找到相應class文件的錯誤,建議使用如下格式在控制檯生成.h頭文件
D:\>javah -classpath . testdll

二、C/C++中所需要做的工作

1、打開VC++,新建工程->win32 DLL,在嚮導中選擇空工程。然後編寫testdll.cpp文件

  1. #include <windows.h>  
  2. #include "TestJNI.h"  
  3. int i = 0;  
  4. JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)  
  5. {  
  6. return i;  
  7. }  
  8. JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)  
  9. {  
  10. i = j;  
  11. }  
  12. int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)   
  13. {   
  14. return TRUE ;   
  15. }  

說明:

(1)必須有DllMain函數,並且DllMain必須返回TRUE,否則系統將終止程序並彈出一個“啓動程序時出錯”對話框,其他兩個爲Java中調用的兩個函數的實現,解釋見最後的補充

(2)把Java編譯生成的TestJNI.h加入到C/C++的工程中,否則上面代碼的include "TestJNI.h"無法引用到

2、編譯上面的testdll.cpp文件,可以生成testdll.dll文件,但是這過程通常會出現:在TestJNI.h中找不到jni.h

解決方法:把Javajdk中的下面這些.h文件複製一份到Microsoft Visual Studio的安裝目錄下的\VC\include文件夾下,例如筆者的是D:\Program Files\Microsoft Visual Studio 10.0\VC\include

[plain] view plaincopy
  1. \jdk\include\jni.h  
  2. \jdk\include\win32\jawt_md.h  
  3. \jdk\include\win32\jni_md.h  

三、結合起來

1、生成的DLL文件的名稱要跟Java代碼中需要調用的testdll一樣,如果不同可以修改文件名,這裏是testdll.dll

2、然後把該dll文件拷貝到TestJNI.class文件的目錄下。

3、使用java testdll 運行它,就可以觀察到結果

說明:如果運行java testdll 出現錯誤:“ 找不到或無法加載主類”,可能是環境變量的classpath鍵值的分號;掉了,一般掉了這個就會出現這種問題

四、最後對TestJNI.h的內容理解補充

[plain] view plaincopy
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. /* Header for class TestJNI*/  
  4. #ifndef _Included_TestJNI  
  5. #define _Included_TestJNI  
  6. #ifdef __cplusplus  
  7. extern "C" {  
  8. #endif  
  9. /*  
  10. * Class: TestJNI  
  11. * Method: get  
  12. * Signature: ()I  
  13. */  
  14. JNIEXPORT jint JNICALL Java_TestJNI_get (JNIEnv *, jclass);  
  15. /*  
  16. * Class: TestJNI  
  17. * Method: set  
  18. * Signature: (I)V  
  19. */  
  20. JNIEXPORT void JNICALL Java_TestJNI_set (JNIEnv *, jclass, jint);  
  21. #ifdef __cplusplus  
  22. }  
  23. #endif  
  24. #endif  
在具體實現的時候,我們只關心兩個函數原型
JNIEXPORT jint JNICALL Java_TestJNI_get (JNIEnv *, jclass); 和
JNIEXPORT void JNICALL Java_TestJNI_set (JNIEnv *, jclass, jint);
這裏JNIEXPORT和JNICALL都是JNI的關鍵字,表示此函數是要被JNI調用的。而jint是以JNI爲中介使JAVA的int類型與本地的int溝通的一種類型,我們可以視而不見,就當做int使用。函數的名稱是JAVA_再加上java程序的package路徑再加函數名組成的。參數中,我們也只需要關心在JAVA程序中存在的參數,至於JNIEnv*和jclass我們一般沒有必要去碰它。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章