天天看點

android 保護

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>

android 保護
android 保護

使用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

android 保護

代碼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。

android 保護

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!!!”

android 保護

在首次使用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)-&gt;;SetByteArrayRegion(env,bytearray,0,len,buffer);将buffer的值copy到bytearray中,函數直接return bytearray就可以了。

class RetObj{public byte[]bytearray;}這個對象作為函數的參數retobj傳出,通過如下函數将retobj中的byte數組指派便于傳出。代碼如下:jclasscls;jfieldIDfid;jbyteArraybytearray;bytearray=(*env)-&gt;;NewByteArray(env,len);(*env)-&gt;;SetByteArrayRegion(env,bytearray,0,len,buffer);cls=(*env)-&gt;;GetObjectClass(env,retobj);fid=(*env)-&gt;;GetFieldID(env,cls,"retbytes","[B"]);(*env)-&gt;;SetObjectField(env,retobj,fid,bytearray);

4、不知道占用多少空間的buffer,如何傳遞出去。

android 保護

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類的開發。

android 保護

基于JNI的嵌入式手機軟體開發執行個體

(1)活動/狀态圖

圖2為捕捉視訊并存儲圖檔的活動/狀态圖

根據圖2的活動/狀态,具體的對應步驟如下:

①發起該流程。

②發起流程後,建立檔案用于存儲圖檔。

⑤操縱攝像頭,捕捉視訊,并将圖像流從攝像頭端傳到緩沖器。

⑥将攝像頭内的圖像流存入緩沖器内,并将緩沖器内的流轉化為檔案流,存為jpg格式的檔案,将指向緩沖器的指針彈棧。

⑦在過程⑥中,如果使用完了序列化的緩沖器,則要重新序列化緩沖器,以備後面使用。

⑨流程結束。

(2)運用JNI技術的視訊捕捉