一,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