招生熱線(xiàn)
0755-86191118 0755-86191118
我的位置: 首頁(yè) > 學(xué)習(xí)專(zhuān)區(qū) > 安卓技術(shù) > android面試之—-談?wù)勀銓?duì)java中native關(guān)鍵字的認(rèn)

android面試之—-談?wù)勀銓?duì)java中native關(guān)鍵字的認(rèn)

2012-02-12 11:23:00
來(lái)源:
[導(dǎo)讀] JNI是J ava Native Interface的 縮寫(xiě)。從Java 1 1開(kāi)始,Java Native Interface (JNI)標(biāo)準(zhǔn)成為java平臺(tái)的一部分,它允許Java代碼和

JNI是J ava Native Interface的 縮寫(xiě)。從Java 1.1開(kāi)始,Java Native Interface (JNI)標(biāo)準(zhǔn)成為java平臺(tái)的一部分,它允許Java代碼和其他語(yǔ)言寫(xiě)的代碼進(jìn)行交互。JNI一開(kāi)始是為了本地已編譯語(yǔ)言,尤其是C和C++而設(shè)計(jì)的,但是它并不妨礙你使用其他語(yǔ)言,只要調(diào)用約定受支持就可以了。

使用java與本地已編譯的代碼交互,通常會(huì)喪失平臺(tái)可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的,比如,使用一些舊的庫(kù),與硬件、操作系統(tǒng)進(jìn)行交互,或者為了提高程序 的性能。JNI標(biāo)準(zhǔn)至少保證本地代碼能工作在任何Java 虛擬機(jī)實(shí)現(xiàn)下。

JNI(Java Native Interface)的書(shū)寫(xiě)步驟

·編寫(xiě)帶有native聲明的方法的java類(lèi)

·使用javac命令編譯所編寫(xiě)的java類(lèi)

·使用javah ?jni java類(lèi)名生成擴(kuò)展名為h的頭文件

·使用C/C++(或者其他編程想語(yǔ)言)實(shí)現(xiàn)本地方法

·將C/C++編寫(xiě)的文件生成動(dòng)態(tài)連接庫(kù)

1) 編寫(xiě)java程序:

這里以HelloWorld為例。

代碼1:

class HelloWorld {

public native void displayHelloWorld();

static {

System.loadLibrary(“hello”);

}

public static void main(String[] args) {

new HelloWorld().displayHelloWorld();

}

}

聲明native方法:如果你想將一個(gè)方法做為一個(gè)本地方法的話(huà),那么你就必須聲明改方法為native的,并且不能實(shí)現(xiàn)。其中方法的參數(shù)和返回值在后面講述。

Load 動(dòng)態(tài)庫(kù):System.loadLibrary(“hello”);加載動(dòng)態(tài)庫(kù)(我們可以這樣理解:我們的方法displayHelloWorld()沒(méi)有實(shí)現(xiàn),但是我們?cè)谙旅婢椭苯邮褂昧耍员仨氃谑褂弥皩?duì)它進(jìn)行初始化)這里一般是以static塊進(jìn)行加載的。同時(shí)需要注意的是 System.loadLibrary();的參數(shù)“hello”是動(dòng)態(tài)庫(kù)的名字。

main()方法

2) 編譯沒(méi)有什么好說(shuō)的了

javac HelloWorld.java

3) 生成擴(kuò)展名為h的頭文件

javah ?jni HelloWorld

頭文件的內(nèi)容:

/* DO NOT EDIT THIS FILE – it is machine generated */

#include

/* Header for class HelloWorld */

#ifndef _Included_HelloWorld

#define _Included_HelloWorld

#ifdef __cplusplus

extern “C” {

#endif

/*

* Class: HelloWorld

* Method: displayHelloWorld

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

(這里我們可以這樣理解:這個(gè)h文件相當(dāng)于我們?cè)趈ava里面的接口,這里聲明了一個(gè)Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我們的本地方法里面實(shí)現(xiàn)這個(gè)方法,也就是說(shuō)我們?cè)诰帉?xiě)C/C++程序的時(shí)候所使用的方法名必須和這里的一致)。

4) 編寫(xiě)本地方法

實(shí)現(xiàn)和由javah命令生成的頭文件里面聲明的方法名相同的方法。

代碼2:

1 #include

2 #include “HelloWorld.h”

3 #include

4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)

{

printf(“Hello world!\n”);

return;

}

注意代碼2中的第1行,需要將jni.h(該文件可以在%JAVA_HOME%/include文件夾下面找到)文件引入,因?yàn)樵诔绦蛑械腏NIEnv、 jobject等類(lèi)型都是在該頭文件中定義的;另外在第2行需要將HelloWorld.h頭文件引入(我是這么理解的:相當(dāng)于我們?cè)诰帉?xiě)java程序的時(shí)候,實(shí)現(xiàn)一個(gè)接口的話(huà)需要聲明才可以,這里就是將HelloWorld.h頭文件里面聲明的方法加以實(shí)現(xiàn)。當(dāng)然不一定是這樣)。然后保存為HelloWorldImpl.c就 ok了。

5) 生成動(dòng)態(tài)庫(kù)

這里以在Windows中為例,需要生成dll文件。在保存HelloWorldImpl.c文件夾下面,使用VC的編譯器cl成。

cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll

注意:生成的dll文件名在選項(xiàng)-Fe后面配置,這里是hello,因?yàn)樵贖elloWorld.java文件中我們loadLibary的時(shí)候使用的名字是hello。當(dāng)然這里修改之后那里也需要修改。另外需要將-I%java_home%\include -I%java_home%\include\win32參數(shù)加上,因?yàn)樵诘谒牟嚼锩婢帉?xiě)本地方法的時(shí)候引入了jni.h文件。

6) 運(yùn)行程序

java HelloWorld就ok。

JNI(Java Native Interface)調(diào)用中考慮的問(wèn)題

在首次使用JNI的時(shí)候有些疑問(wèn),后來(lái)在使用中一一解決,下面就是這些問(wèn)題的備忘:

1。 java和c是如何互通的?

其實(shí)不能互通的原因主要是數(shù)據(jù)類(lèi)型的問(wèn)題,jni解決了這個(gè)問(wèn)題,例如那個(gè)c文件中的jstring數(shù)據(jù)類(lèi)型就是java傳入的String對(duì)象 ,經(jīng)過(guò)jni函數(shù)的轉(zhuǎn)化就能成為c的char*。

對(duì)應(yīng)數(shù)據(jù)類(lèi)型關(guān)系如下表:

Java 類(lèi)型 本地c類(lèi)型 說(shuō)明

boolean jboolean 無(wú)符號(hào),8 位

byte jbyte 無(wú)符號(hào),8 位

char jchar 無(wú)符號(hào),16 位

short jshort 有符號(hào),16 位

int jint 有符號(hào),32 位

long jlong 有符號(hào),64 位

float jfloat 32 位

double jdouble 64 位

void void N/A

2. 如何將java傳入的String參數(shù)轉(zhuǎn)換為c的char*,然后使用?

java 傳入的String參數(shù),在c文件中被jni轉(zhuǎn)換為jstring的數(shù)據(jù)類(lèi)型,在c文件中聲明char* test,然后test = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);注意:test使用完后,通知虛擬機(jī)平臺(tái)相關(guān)代碼無(wú)需再訪(fǎng)問(wèn):(*env)->ReleaseStringUTFChars(env, jstring, test);

3. 將c中獲取的一個(gè)char*的buffer傳遞給java?

這個(gè)char*如果是一般的字符串的話(huà),作為string傳回去就可以了。如果是含有’\0’的buffer,最好作為bytearray傳出,因?yàn)榭梢灾贫╟opy的length,如果copy到string,可能到’\0’就截?cái)嗔恕?/p>

有兩種方式傳遞得到的數(shù)據(jù):

一種是在jni中直接new一個(gè)byte數(shù)組,然后調(diào)用函數(shù)(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);將buffer的值copy到bytearray中,函數(shù)直接return bytearray就可以了。

一種是return錯(cuò)誤號(hào),數(shù)據(jù)作為參數(shù)傳出,但是java的基本數(shù)據(jù)類(lèi)型是傳值,對(duì)象是傳遞的引用,所以將這個(gè)需要傳出的byte數(shù)組用某個(gè)類(lèi)包一下,如下:

class RetObj

{

public byte[] bytearray;

}

這個(gè)對(duì)象作為函數(shù)的參數(shù)retobj傳出,通過(guò)如下函數(shù)將retobj中的byte數(shù)組賦值便于傳出。代碼如下:

jclass cls;

jfieldID fid;

jbyteArray bytearray;

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的c文件中new出空間,傳遞出去。java的數(shù)據(jù)不初始化,指向傳遞出去的空間即可。

評(píng)論
學(xué)計(jì)算機(jī)專(zhuān)業(yè)難嗎 學(xué)計(jì)算機(jī)專(zhuān)業(yè)好不好 學(xué)計(jì)算機(jī)有什么專(zhuān)業(yè) 學(xué)計(jì)算機(jī)有哪些專(zhuān)業(yè) 學(xué)計(jì)算機(jī)學(xué)習(xí)什么專(zhuān)業(yè)好 學(xué)計(jì)算機(jī)學(xué)什么專(zhuān)業(yè)好 學(xué)計(jì)算機(jī)學(xué)什么專(zhuān)業(yè) 初中生學(xué)什么技術(shù)好 NET軟件開(kāi)發(fā)工程師 linux運(yùn)維工程師 運(yùn)維部門(mén)主管 高中生如何學(xué)IT 男孩學(xué)什么技術(shù)好就業(yè) 高考結(jié)束后適合學(xué)什么技術(shù) 深圳IT培訓(xùn)學(xué)校哪家好 計(jì)算機(jī)專(zhuān)業(yè)學(xué)什么 北大青鳥(niǎo)深圳嘉華培訓(xùn)怎么樣 北大青鳥(niǎo)學(xué)費(fèi)一年多少 黃貝北大青鳥(niǎo) 企業(yè)化帶班 高考畢業(yè)生學(xué)什么技術(shù)好找工作 高中生學(xué)什么專(zhuān)業(yè)好找工作 北大青鳥(niǎo)開(kāi)學(xué)時(shí)間 北大青鳥(niǎo)紀(jì)錄片 翠竹北大青鳥(niǎo) 明日之星總決賽 高考落榜讀什么學(xué)校有好出路 2017專(zhuān)科錄取分?jǐn)?shù)線(xiàn) 現(xiàn)在什么專(zhuān)業(yè)就業(yè)前景好 200分能上什么學(xué)校 高考多少分能上專(zhuān)科學(xué)校 高中畢業(yè)后學(xué)什么好 高考沒(méi)被錄取怎么辦 校園形象代言人 北大青鳥(niǎo)學(xué)費(fèi)是多少 JAVA6 高考失利怎么辦 筍崗北大青鳥(niǎo) 華富北大青鳥(niǎo) 大合唱 明日之星節(jié)目 園嶺北大青鳥(niǎo) 北大青鳥(niǎo)什么時(shí)候開(kāi)學(xué) 現(xiàn)在什么專(zhuān)業(yè)好就業(yè) 深圳北大青鳥(niǎo)學(xué)校的學(xué)費(fèi)是多少
好吊妞免费视频在线观看,久久亚洲国产人成综合网,久久精品国产2020,欧美精品综合在线
亚洲一区中文字幕在线观看 | 一级特黄录像免中文 | 亚洲午夜免费福利视频 | 在线观看免费高清AⅤ片 | 亚洲国产精品综合久久久 | 亚洲中文乱码字幕不卡 |