Java JNI 的簡單介紹

一,Java JNI 介紹

       Java jni本意是Java native interface(Java本地接口),是爲了方便Java調用c、c++等本地代碼所封裝的一層接口。Java

的優點是跨平臺,但是作爲優點的同時,其在本地交互的時候就變成了缺點。

        Java的跨平臺特性導致其本地交互的能力不夠強大,一些和操作系統相關的特性Java無法完成,於是Java提供了jni,專門

用於和本地代碼交互,這樣就增強了Java語言的本地交互能力。

        通過Java jni,用戶可以調用用c、c++所編寫的native code。在html5視頻和一些與底層系統關聯的項目開發中就採用了

jni,android只用於ui的顯示,其業務邏輯都是通過native code所完成的,android代碼只是負責通過jni和native進行交互,這

樣也提高了代碼的可維護性。

二,Java JNI 的簡單使用

        通過Java jni來調用native code,需要如下幾個步驟:

        1,聲明native接口函數,語法如下:public native static void set(int i);  其中native是Java的關鍵字,被native修飾的函

數都是本地函數的接口,其具體功能要被native code來實現。

//testdll.java
public class testdll
{
    static
    {
        System.loadLibrary("my");  //加載本地庫文件my.so
    }
    public native static int get();
    public native static void set(int i);
    public static void main(String[] args)
    {
        testdll test = new testdll();
        test.set(3721);
        System.out.println(test.get());
    }
}

        2,用javah命令導出Java jni中定義的本地方法的聲明,這個是.h格式的頭文件

        首先用javac編譯出class文件,然後在用javah導出頭文件,我們發現導出的頭文件,其函數聲明發生了變化,其中jint是jni

定義的用來和c/c++交互的數據類型,可以當作int來用。

//testdll.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class testdll */

#ifndef _Included_testdll
#define _Included_testdll
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     testdll
 * Method:    get
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_testdll_get
  (JNIEnv *, jclass);

/*
 * Class:     testdll
 * Method:    set
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_testdll_set
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif

        3. 實現Java jni中定義的native methods

        有了頭文件以後,就可以用本地函數去實現頭文件中聲明的native函數了,通常用c和c++來實現native函數。

//my.c
#include "jni.h"
#include "testdll.h"
#include<stdio.h>

static int i;

JNIEXPORT jint JNICALL Java_testdll_get(JNIEnv *a, jclass b)
{
    return i;
}

JNIEXPORT void JNICALL Java_testdll_set(JNIEnv *a, jclass b, jint j)
{
    FILE *f;
    f=fopen("my.txt","a+");
    fwrite("嘿嘿你好啊xixi",1,14,f);
    fclose(f);
    i = j;
}

        4.將native code編譯成shared library供Java調用

        針對Linux來說,就是.so文件,針對Windows來說就是.dll文件,Linux下用g++、gcc進行編譯,這裏不對其進行介紹了。

對Windows來說,編譯生成dll一般是通過vc來完成的。Windows下的動態鏈接庫分爲win32 dll和mfc dll,其中win32 dll可以

供各種語言調用,而mfc dll則會受到一些限制。這裏介紹win32 dll。生成一個win32 dll,要定義被導出的函數,有兩種方式,

函數名稱前加_declspec(dllexport)或者定義def文件,然後用vc進行編譯,這樣做並不算複雜,但是我發現了一種更容易的方

法,我們只需要按照c/c++的語法規範實現native函數,不需要定義被導出的函數,然後調用vc的編譯工具cl.exe就可以了。首先

將testdll.h和my.c拷貝到Microsoft Visual Studio x.x\VC\bin中,同時將jdk中include目錄中的所有文件也都拷貝到Microsoft

Visual Studio x.x\VC\bin中(這樣做不是必須的,但是如果不這樣,你調用cl命令的時候就要帶上一大串路徑信息),接着調出

vs再帶的命令行工具,進入bin目錄,然後執行cl -I . -LD my.c -Femy.dll(.表示當前目錄,I表示將在當前目錄搜索包含的頭文

件,-LD後面表示源文件,-Fe後面緊跟的是目標文件),ok,my.dll生成了,將my.dll拷貝到Java文件所在的目錄,執行Java命

令,成功執行。上面只是個簡單的示例,實際開發中還會有一些需要注意的問題,比如各種類型參數的傳遞,native code調用

dll或so的情況,這裏就不做介紹了。

轉自:http://blog.csdn.net/singwhatiwanna/article/details/9061545

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