JNI入門

JNI是Java Native Interface的縮寫,中文即JAVA本地調用。從Java1.1開始,JNI標準成爲java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI一開始是爲了本地已編譯語言,尤其是C和C++而設計的,但是它並不妨礙你使用其他語言,只要調用約定受支持就可以了。

通常有以下幾種情況我們需要使用JNI來實現:

1.標準的java類庫沒有提供你的應用程序所需要的功能,通常這些功能是平臺相關的。

2.你希望在java程序中使用一些已經有的類庫或者應用程序,而他們並非用java語言編寫的。

3.程序的某些部門對速度要求比較苛刻,你選擇用匯編或者C語言來實現,並在java語言中調用他們。

關係如下圖所示:


一般書寫分以下幾步進行:

 1.編寫帶有native聲明的方法的java類

 2.使用javac命令編譯縮寫的java類,然後使用javah + java類名生成h頭文件

 3.使用C\C++實現本地方法

 4.將C\C++編寫的文件生成動態鏈接庫

 5.運行程序,OK。

下面演示一個示例程序HelloWorld。

 1.編寫java類

    首先,我們在硬盤上建立一個文件夾hello作爲我們的工作目錄,然後編寫java代碼,命名爲HelloWorld.java,如下所示:

class HelloWorld {
   public native void displayHelloWorld();//所有native關鍵詞修飾的都是對本地的聲明
   static {
      System.loadLibrary("hello"); //載入本地庫
   }
   public static void main(String[] args) {
      new HelloWorld().displayHelloWorld();
   }
}
注重我們的displayHelloWorld()方法的聲明,它有一個關鍵字native,表明這個方法使用java以外的語言實現。方法不包括實現,因爲我們要用c/c++語言實現它。

注重System.loadLibrary("hello")這句代碼,它是在靜態初始化塊中定義的,系統用來裝載hello共享庫,這就是我們在後面生成的hello.dll(假如在其他的操作系統可能是其他的形式,比如hello.so)
 2.編譯java代碼

    首先安裝java jdk,我安裝在C盤下,然後設置環境變量:

1.打開我的電腦--屬性--高級--環境變量
 
2.新建系統變量JAVA_HOME 和CLASSPATH

           變量名:JAVA_HOME   變量值:C:\Program Files\Java\jdk1.7.0

           變量名:CLASSPATH   變量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;

  3. 選擇“系統變量”中變量名爲“Path”的環境變量,雙擊該變量,把JDK安裝路徑中

bin目錄的絕對路徑,添加到Path變量的值中,並使用半角的分號和已有的路徑進行分隔。

變量名:Path 變量值:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

          打開命令行,進入hello目錄下,輸入命令javac HelloWorld.java,生成HelloWorld.class文件,如下圖:

     

3.生成h文件

   輸入命令 javah 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:    displayHelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
(這裏我們可以這樣理解:這個h文件相當於我們在java裏面的接口,這裏聲明瞭一個Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然後在我們的本地方法裏面實現這個方法,也就是說我們在編寫C/C++程序的時候所使用的方法名必須和這裏的一致)。

4.編寫本地實現代碼

   代碼:

#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>

JNIEXPORT void JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj) {
 
  printf("Hello world!\n");
  return;
}
注意代碼中的第1行,需要將jni.h(該文件可以在%JAVA_HOME%/include文件夾下面找到)文件引入,因爲在程序中的JNIEnv、 jobject等類型都是在該頭文件中定義的;另外在第2行需要將HelloWorld.h頭文件引入(我是這麼理解的:相當於我們在編寫java程序的時候,實現一個接口的話需要聲明纔可以,這裏就是將HelloWorld.h頭文件裏面聲明的方法加以實現。當然不一定是這樣)。然後保存爲 HelloWorldImpl.c就ok了。

5.生成動態庫

   這裏以在Windows中爲例,需要生成dll文件。在保存HelloWorldImpl.c文件夾下面,使用VC的編譯器cl成。 

   cl -I“%JAVA_HOME%\include” -I“%JAVA_HOME%\include\win32” -LD HelloWorldImpl.c -Fehello.dll

   注意1:生成的dll文件名在選項-Fe後面配置,這裏是hello(中間沒有空格),因爲在HelloWorld.java文件中我們loadLibary的時候使用的名字是hello。當然這裏修改之後那裏也需要修改。另外需要將-I%java_home%\include -I%java_home%\include\win32參數加上,因爲在第四步裏面編寫本地方法的時候引入了jni.h文件。

     注意2:使用cl編譯器時我們也需要配置一下環境變量:

   如果你是把VC安裝在默認路徑,那麼要把操作系統的默認路徑(即PATH)設置爲以下四個路徑,用分號隔開
   C:\Program Files\Microsoft Visual Studio\Common\Tools\WinNT
   C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin
   C:\Program Files\Microsoft Visual Studio\Common\Tools
   C:\Program Files\Microsoft Visual Studio\VC98\bin

    新建環境變量include,變量值爲C:\Program Files\Microsoft Visual Studio\VC98\include

    新建環境變量lib,變量值爲C:\Program Files\Microsoft Visual Studio\VC98\lib

    保存。

    編譯完成後,會生成hello.dll文件,如下圖所示:

    

6.運行程序

   將hello.dll複製到工作目錄下,運行java HelloWorld,輸出Hello World!如下圖所示:

   

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章