1. 程式人生 > >Java的JNI學習和簡單例項

Java的JNI學習和簡單例項

JNI簡介

   JNI(Java NativeInterface) ,Java本地介面。用Java去呼叫其他語言編寫的程式,比如C或C++。JNI作為二者連線的橋樑。
Java的跨平臺本質主要是由於JVM不是跨平臺的,JNI本身也不是跨平臺的,即JNI是與特定平臺相關的。

JNI的例項

   主要實現了兩個小例項,一個是無引數無返回值的Native方法,一個是帶引數有返回值的Native方法。主要介紹第一個例子,
   第二個例子就不細說了,後面會附上原始碼。

例項一:

1.在Java類中宣告Native方法,並且編譯成class(若使用IDE工具一般會自動編譯了,否則自己用,程式碼如下:

package com.jni.learn.simple;

//問候的類
public class Hello {
    // 宣告本地方法
 public native void sayHello();

}

2.使用javah程式,將上步中的.class檔案生成標頭檔案

使用的命令為:javah –jni  xxx(class檔案的全路徑,即包括了包名),在這一步,開啟cmd進入到該Java專案下的bin目錄(一般需要在bin目錄下使用命令才能生效),使用

javah –jni com.jni.learn.simple.hello

然後在bin目錄下會生成了一個C/C++的標頭檔案,如下圖:
這裡寫圖片描述

生成的標頭檔案
標頭檔案的程式碼如下:

#include

#ifndef _Included_com_jni_learn_simple_Hello

#define _Included_com_jni_learn_simple_Hello

#ifdef __cplusplus

extern "C" {

#endif

JNIEXPORT void JNICALL Java_com_jni_learn_simple_Hello_sayHello(JNIEnv *, jobject);

#ifdef __cplusplus

}
#endif

#endif
  1. 使用其他語言(如C,C++)實現上述標頭檔案中的函式,生成動態庫,供Java程式使用,這一步很關鍵,卻也是比較繁瑣。

3.1 首先使用VS2010建立一個Win32的控制檯應用程式,在設定應用程式的視窗選擇如下:

這裡寫圖片描述

接著點選完成。

3.2 匯入標頭檔案

        在這一步裡我們需要匯入在前面生成的標頭檔案com_jni_learn_simple_Hello.h,此外還需要匯入另外的java提供的兩個標頭檔案
  (需要的原因是生成的標頭檔案依賴於它們),一個是jin.h,另一個是jni_md.h分別在java的安裝目錄下的include目錄和
  include\win32目錄。我把它們都放入到了VS2010的安裝目錄下的VC\include目錄下了,那麼在我們的C++專案中就可以直接引用
  這些標頭檔案了。

3.3 建立cpp檔案,匯入標頭檔案,實現宣告的函式

建立了一個NativeHello.cpp檔案,實現的程式碼如下:

#include <iostream>
#include <com_jni_learn_simple_Hello.h>
using namespace std;

JNIEXPORT void JNICALL Java_com_jni_learn_simple_Hello_sayHello(JNIEnv *, jobject){
    cout<<"Hello World!"<<endl;
}
/* DO NOT EDIT THIS FILE - it is machine generated */

/* Header for class com_jni_learn_simple_Hello */
#include <jni.h>
#ifndef _Included_com_jni_learn_simple_Hello
#define _Included_com_jni_learn_simple_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jni_learn_simple_Hello
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_jni_learn_simple_Hello_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

3.4 編譯,生成dll的動態庫檔案

    這裡有個問題需要注意,編譯的時候有32位和64位之分,取決於你的java的版本,VS2010預設的是32位,在這裡我選擇64位編譯,
其他工具也一樣需要注意。

VS2010設定64位編譯的操作,在工具欄中,選擇如下圖的中間的下拉框將會出現配置管理器的選項,然後我們自己新建一個x64的管理器,並且選擇使用它即可,完成後結果如下圖。
這裡寫圖片描述

配置好後,然後點選編譯,將會生成一個nativeHello.dll檔案。

4.匯入生成的DLL檔案,Java完成呼叫

   將生成的DLL檔案複製到Java專案中的src目錄下,或者直接放到java的安裝目錄的include目錄下,兩種方式都行,一個是區域性
   一個是全域性。

這時,我們可以通過java程式碼來載入dll檔案,使用Native方法了,具體程式碼如下圖:

package com.jni.learn.simple;

public class SayHelloDemo {

    public static void main(String[] args) {
      // 載入動態連結庫 
      System.loadLibrary("nativeHello"); 
      Hello hello = new Hello();  
      hello.sayHello();  
    }

}
   在程式碼中的System.loadLibrary()作用是載入dll檔案,它需要傳入dll檔案的路徑,預設是從java安裝目錄下和當前目錄下查詢。

執行結果如下圖:
這裡寫圖片描述

以上就是第一個例項。

例項二: