JNI是Java Native Interface的縮寫,中文為JAVA本地調用。從Java1.1開始,Java Native Interface(JNI)标準成為java平台的一部分,它允許Java代碼和其他語言寫的代碼進行互動。JNI一開始是為了本地已編譯語言,尤其是C和C++而設計的,但是它并不妨礙你使用其他語言,隻要調用約定受支援就可以了。使用java與本地已編譯的代碼互動,通常會喪失平台可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的,比如,使用一些舊的庫,與硬體、作業系統進行互動,或者為了提高程式的性能。JNI标準至少保證本地代碼能工作在任何Java虛拟機實作下。
<a href="http://www.baike.com/wiki/JNI">編輯摘要</a>
<dl></dl>
使用javac指令編譯所編寫的java類
使用javah jnijava類名生成擴充名為h的頭檔案
使用C/C++實作本地方法
1、編寫java程式:這裡以Hello World為例。
代碼1:
class HelloWorld{
public native void displayHelloWorld();
static{
System.loadLibrary("hello");
}
public static void main(String[]args){
newHelloWorld().displayHelloWorld();
2、編譯
javacHelloWorld.java
3、生成擴充名為h的頭檔案javah
jni HelloWorld頭檔案的内容:/*DO NOT EDIT THIS FILE-it is machine generated*/
1.include
/*HeaderforclassHelloWorld*/
1.ifndef _Included_HelloWorld
2.define _Included_HelloWorld
3.if def__cplusplus
extern"C"{
1.endif
/*
*Class:HelloWorld
*Method:displayHelloWorld
*Signature:()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv*,jobject);
1.ifdef__cplusplus
2.endif
代碼2:
1#include
2#include"HelloWorld.h"
3#include
4JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv*env,jobjectobj){printf("Helloworld!\n");return;}
5、生成動态庫
6、運作程式javaHelloWorld。
class weiqiong{static{System.loadLibrary("testjni");//載入靜态庫,test函數在其中實作}private native void testjni();//聲明本地調用public void test(){testjni();}public static void main(String args[]){weiqionghaha=new weiqiong();haha.test();}}
2、然後執行javac weiqiong.java,如果沒有報錯,會生成一個weiqiong.class。
3、然後執行javah weiqiong,會生成一個檔案weiqiong.h檔案,其中有一個函數的聲明如下:
JNIEXPORT void JNICALL Java_weiqiong_testjni(JNIEnv*,jobject);
4、建立檔案testjni.c将上面那個函數實作,内容如下:
2.include
JNIEXPORT void JNICALL Java_weiqiong_testjni(JNIEnv*env,jobjectobj){printf("haha---------gointoc!!!\n");}
5、為了生成.so檔案,建立makefile檔案如下:
libtestjni.so:testjni.omakefilegcc-Wall-rdynamic-shared-olibtestjni.sotestjni.otestjni.o:testjni.cweiqiong.hgcc-Wall-ctestjni.c-I./-I/usr/java/j2sdk1.4.0/include-I/usr/java/j2sdk1.4.0/include/linuxcl:rm-rf*.o*.so注意:gcc前面是tab空,j2sdk的目錄根據自己裝的j2sdk的具體版本來寫,生成的so檔案的名字必須是loadLibrary的參數名前加“lib”。
7、執行java weiqiong,列印出結果:“haha---------gointoc!!!”
在首次使用JNI的時候有些疑問,後來在使用中一一解決,下面就是這些問題的備忘:
1、java和c是如何互通的。
其實不能互通的原因主要是資料類型的問題,jni解決了這個問題,例如那個c檔案中的jstring資料類型就是java傳入的String對象,經過jni函數的轉化就能成為c的char*。
對應資料類型關系如下表:
2、如何将java傳入的String參數轉換為c的char*,然後使用。
3、将c中擷取的一個char*的buffer傳遞給java。
有兩種方式傳遞得到的資料:
一種是在jni中直接new一個byte數組,然後調用函數(*env)->;SetByteArrayRegion(env,bytearray,0,len,buffer);将buffer的值copy到bytearray中,函數直接return bytearray就可以了。
class RetObj{public byte[]bytearray;}這個對象作為函數的參數retobj傳出,通過如下函數将retobj中的byte數組指派便于傳出。代碼如下:jclasscls;jfieldIDfid;jbyteArraybytearray;bytearray=(*env)->;NewByteArray(env,len);(*env)->;SetByteArrayRegion(env,bytearray,0,len,buffer);cls=(*env)->;GetObjectClass(env,retobj);fid=(*env)->;GetFieldID(env,cls,"retbytes","[B"]);(*env)->;SetObjectField(env,retobj,fid,bytearray);
4、不知道占用多少空間的buffer,如何傳遞出去。
JNI(JavaNativeInterface,Java本地化方法)。圖l是JNI技術實作的一般步驟。
//Compute.java
publicclassCompute{
publicnativedoublecomp(doubleparams);
//調用動态連結庫
System.loadLibrary(“mathlib”);
(2)編譯成位元組代碼
(3)生成相關JNI方法的頭檔案
這個過程的實作一般是通過利用jlavah-jni*class生成的,也可以手工生成該檔案;但是由于Java虛拟機是根據一定的命名規範完成對JNI方法的調用,是以手工編寫頭檔案需要特别小心。
上述檔案産生的頭檔案部分代碼如下:
//Compute.h
;
extern“C”{
JNIEXPORTjdoubleJNICALLJava_Compute_comp(JNI-Env*,jobject,jdoubleArray);
(4)編寫相應方法的實作代碼
(5)将JNI實作代碼編譯成動态連結庫
編譯過程是利用C/C++編譯器實作的,當要使用生成的動态連結庫時,調用者類中需要顯式調用該連結庫。
經過上述處理,基本上完成了一個包含本地化方法的Java類的開發。
基于JNI的嵌入式手機軟體開發執行個體
(1)活動/狀态圖
圖2為捕捉視訊并存儲圖檔的活動/狀态圖
根據圖2的活動/狀态,具體的對應步驟如下:
①發起該流程。
②發起流程後,建立檔案用于存儲圖檔。
⑤操縱攝像頭,捕捉視訊,并将圖像流從攝像頭端傳到緩沖器。
⑥将攝像頭内的圖像流存入緩沖器内,并将緩沖器内的流轉化為檔案流,存為jpg格式的檔案,将指向緩沖器的指針彈棧。
⑦在過程⑥中,如果使用完了序列化的緩沖器,則要重新序列化緩沖器,以備後面使用。
⑨流程結束。
(2)運用JNI技術的視訊捕捉