Java jni本意是Java native interface(Java本地接口),是爲了方便Java調用c、c++等本地代碼所封html
裝的一層接口。你們都知道,Java的優勢是跨平臺,可是做爲優勢的同時,其在本地交互的時候就編程了缺點。html5
Java的跨平臺特性致使其本地交互的能力不夠強大,一些和操做系統相關的特性Java沒法完成,因而Java提供了java
jni專門用於和本地代碼交互,這樣就加強了Java語言的本地交互能力。android
經過Java jni,用戶能夠調用用c、c++所編寫的native code。在html5視頻的開發中就採用了jni,c++
android只用於ui的顯示,其業務邏輯都是經過native code所完成的,android代碼只是負責經過jni和native進編程
行交互。函數
經過Java jni來調用native code,須要以下幾個步驟:工具
1.聲明native接口函數,語法以下:public native static void set(int i);ui
其中native是Java的關鍵字,被native修飾的函數都是本地函數的接口,其具體功能要被native code來操作系統
實現。
//testdll.java
public class testdll
{
static
{
System.loadLibrary("my");
}
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的狀況,這裏就不作介紹了,完畢。