JNI樣本
一、JNI簡介
JNI:Java Native Interface,是Java語言提供的一種通用介面,用於Java代碼與本地化代碼的互動。所謂本地化代碼是指直接編譯成的與機器相關的二進位代碼,而非Java位元組碼之類的中間代碼。Windows下面的可執行檔,DLL等,Linux下面的可執行檔和SO檔案等,都是二進位代碼。
JNI允許Java語言編寫的程式與其他語言編寫的程式庫(DLL, SO)或可執行檔進行互操作,包括彙編、C、C++。JNI產生的原因在於以下幾種需求:
(1). 你的應用程式需要使用系統相關的功能,而Java代碼不支援或是難以辦到。這個比較典型的是實現托盤表徵圖,有幾種現成的方案都是用的JNI做的,名字好像是叫做TrayIcon和StayOnTop。當然啦,如果是用的Java1.6,那就要另當別論了。
(2). 已有其他語言寫好的類庫或程式,希望Java程式可以使用它們。
(3). 出於更高的效能要求,希望使用彙編或是C/C++語言來實現部分功能。
其他的理論的東西就不多說了,JNI Tutorial講得很清楚。強烈建議閱讀。
二、JNI的開發步驟
這裡以使用C++編寫本地化方法實現為例,開發一個使用JNI的Demo程式,具體步驟如下所示:
(1). 編寫帶有native方法的java類
(2). 使用javac命令編譯所編寫的java類
(3). 使用javah命令處理類檔案,產生C/C++標頭檔
(4). 使用C/C++實現本地方法
(5). 將C/C++編寫的檔案產生動態串連庫
三、下面我們開始編寫HelloWorld程式,由於涉及到要編寫c/c++代碼因此我們會在開發中使用Microsoft VC++工具。
1.編寫java代碼
在c盤根目錄下建立java檔案,內容如下:
class HelloWorld{ public native void displayHelloWorld(); static { System.loadLibrary("hello"); } public static void main(String[] args) { new HelloWorld().displayHelloWorld(); }}
注意System.loadLibrary("hello")這句代碼,它是在靜態初始化塊中定義的,系統用來裝載hello共用庫,這就是我們在後面產生的hello.dll(如果在其他的作業系統可能是其他的形式,比如hello.so)
2. 編譯java代碼
javac HelloWorld.java 產生HelloWorld.class檔案
3. 建立.h檔案
javah HelloWorld
4. 編寫本地實現代碼
首先:開啟VC++6.0,建立->工程 -> win32 Dynamic-Link Library ,名字隨便取,在嚮導中選擇空工程。
然後:把剛才javah產生的那個標頭檔複製到剛才建立的工程中。然後 檔案->建立->文字檔, 自己做一個.c檔案(一定要加.c或者.c++的尾碼),檔案名稱為hello,實現自己的native函數。清單如下:
#include <jni.h>#include "HelloWorld.h"#include <stdio.h>JNIEXPORT void JNICALLJava_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj){ printf("Hello world!\n"); return;}
儲存編譯,會發生錯誤:
a. 缺少jni.h。 jni.h通常在 jdk/include/, 可以先拷貝到VC安裝目錄下的include目錄下。一勞永逸,以後可以方便使用JNI技術。
b. 缺少jni_md.h。在jdk\include\win32裡找到jni_md.h,複製到c++工程下。
編譯後有可能會提示叫指定可執行檔,選中Debag檔案夾下的一個.exe檔案就行了(原理不懂 =,=)。這樣在c++工程下的debug檔案夾下會有產生的.dll檔案。複製到
C盤根目錄,然後在命令列輸入
java HelloWorld
就可以看到結果了。
PS:#i nclude<file.h> 與 #i nclude "file.h"的區別?
前者是從Standard Library的路徑尋找和引用file.h,而後者是從當前工作路徑搜尋並引用file.h。